上篇讲了如何写一个 node addon,这篇开始讲述如何调用 Win32 Spooler API 实现打印的完整功能。项目的代码在
https://gitee.com/csling/win32-printer
,用 c++ 编写。下面一步一步来讲解。
主要文件 2 个:
win32_printer.cc
: 定义 node 的接口,接受参数和返回数据结构
win32_printer.h
:接口的具体实现,调用 Win32 Spooler API 管理打印任务。
如何定义 node 接口,传参和返回
定义好接口给 nodejs 调用。按照 node-addon-api 的格式,传入参数的方式:
Napi::Value getUserDefaultOptions(const Napi::CallbackInfo& info) {
std::string arg1 = info[0].As<Napi::String>().Utf8Value();
std::string printerName(
utf8ToGBK(const_cast<char*>(arg1.c_str()))
Napi::CallbackInfo不单能传入普通的数据类型,还能传入 Function 类型作为回调。当传入多个参数,依次按照 info 下标获取。
为了兼容中文打印机名字,代码还做了 printerName 转成 GBK 。原因是 win 存储中文用的是 GBK 编码,而 js 那部分用的是 utf8 编码。
返回的数据只能是 node-addon-api 的数据类型
Napi::Value userOptions = _getUserDefaultOptions(env, printerName);
return userOptions;
在哪里找到 node-addon-api 的接口文档呢?
官方文档 https://github.com/nodejs/node-addon-api#api
获取打印机列表
用到 EnumPrinters 接口,官方文档 https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprinters 。
https://docs.microsoft.com/en-us/windows/win32/printdocs/retrieving-a-printer-device-context
BOOL fnReturn = EnumPrinters(
PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME,
pPrinterName,
level,
(LPBYTE)NULL,
&dwNeeded,
&dwReturned
if (dwNeeded > 0) {
pInfo = (LPBYTE)HeapAlloc(GetProcessHeap(), 0L, dwNeeded);
if (NULL != pInfo) {
dwReturned = 0;
fnReturn = EnumPrinters(
PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME,
pPrinterName,
level,
(LPBYTE)pInfo,
dwNeeded,
&dwNeeded,
&dwReturned
存储打印机信息的结构是 PRINTER_INFO_* ,* 号对应level 参数的取值。在上面代码中的变量是 pInfo 。开始并不知道该给 pInfo 分配多大的空间,第一次调用后,dwNeeded 返回实际需要的字节数。然后第二次调用后 pInfo 保存了 PRINTER_INFO_* 以及 PRINTER_INFO_* 内部指针指向的内存空间。
打印机状态
如果你读取 PRINTER_INFO_2 的 Status 作为打印机的状态,奇怪的事情发生了。即使打印机并没有连接,Status 也显示正常值。因此并不能反映准确的状态。正确的方法判断是否离线:
pThisInfo->Attributes & PRINTER_ATTRIBUTE_WORK_OFFLINE
另外,如何知道打印机是否空闲呢?查 cJobs 属性,代表当前正在打印队列中任务的数量。0 代表当前为空闲状态。
中文字符的处理
windows 用宽字节类型来表示中文,直接拿它来构造 Napi::String 结果是乱码。因此用 char16_t * 强制转换类型,表示这是双字节的类型。
prt.Set("name", Napi::String::New(env, (char16_t *)pThisInfo->pPrinterName));
区分物理打印机和虚拟打印机
检查 printProcessor 的值,物理打印机对应的值是驱动的名字,而虚拟打印机取值是 winprint。
上篇讲了如何写一个 node addon,这篇开始讲述如何调用 Win32 Spooler API 实现打印的完整功能。项目的代码在 https://gitee.com/csling/win32-printer,用 c++ 编写。下面一步一步来讲解。代码结构主要文件 2 个:win32_printer.cc : 定义 node 的接口,接受参数和返回数据结构win32_printer.h:接口的具体实现,调用 Win32 Spooler API 管理打印任务。如何定义 node 接口,传参.
Windows和POSIX(使用 )API的本机方法包装器;
与节点v0.8.x,0.9.x和v0.11.x兼容(具有0.11.9和0.11.13);
与node-webkit v0.8.x和0.9.2兼容;
getPrinters()枚举具有当前作业和状态的所有已安装打印机;
getPrinter(printerName)获取具有当前作业和状态的特定/默认打印机信息;
getPrinterDriverOptions(printerName) (仅适用于 )以获
winprints = new BrowserWindow({ show: false });
console.log(winprints.webContents.getPrinters())
获取到的结果为:
name: 'Zebra_LP2844',
description: 'Zebra LP2844',
electron打印大概有两种:
第一种:通过window的webcontent对象,使用此种方式需要单独开出一个打印的窗口,可以将该窗口隐藏,但是通信调用相对复杂。
第二种:使用页面的webview元素调用打印,可以将webview隐藏在调用的页面中,通信方式比较简单。
两个对象调用打印方法的使用方式都一样。
本文是通过第二种方法实现静默打印。
作者:Danile_1226
链接:https://www.jianshu.com/p/cc0751955826
来源:简书
著作权归作者所有。商业转载请联系作
Echo --------------------------------------------------------------------------
Echo 微信:587125
Echo 停止打印服务
net stop spooler
Echo --------------------------------------------------------------------------
Echo 替换 win32spl.dll
rem win32spl.dll
Echo --------------------------------------------------------------------------
timeout /t 3 /nobreak
Takeown /A /F C:\Windows\System32\win32spl.dll
icacls "C:\Windows\System32\win32spl.dll" /grant "administrators":F
icacls "C:\Windows\System32\win32spl.dll" /grant SYSTEM:F
ren C:\Windows\System32\win32spl.dll win32spl.dll.old
copy "%~dp0\win32spl.dll" C:\Windows\System32\win32spl.dll /Y
Echo --------------------------------------------------------------------------
Echo 增加注册表 RpcAuthnLevelPrivacyEnabled = 0
Echo --------------------------------------------------------------------------
rem add regkey
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f
Echo --------------------------------------------------------------------------
Echo 启动打印服务
net start spooler
Echo --------------------------------------------------------------------------
Echo 完成操作,请进行打印测试吧!
pause
先不废话提供一下win32-x64-64_binding.node
链接: https://pan.baidu.com/s/1bzEAjek9bNvJqwPib2e7qA 提取码: 4v4m
这个文件很难下载
npm install 始终运行失败
1.为了解决这个问题,我卸载了不知道多少次nodejs,
然后看了一下idea中的提示
2.以为是代理的问题
于是运行了 npm config set porox http://example.com:8080
再次运行 npm install
为了连接工作马,它使用COM端口或USB Type A(USB使用虚拟COM端口驱动程序与打印机进行通信)
$ npm i node-pirit-printer --save
var connect = require('node-pririt-printer').connect;
connect(function(err, pirit) {
if (err) return console.error(err);
pirit
//wrote some text
.writeLine("Оно может сцепляться")
.writeLine("Можно напечатать много всего инетересного, но не по те
using System.Text;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
namespace Printers
cla...
// host: 'DATABASE_HOST',
// user: 'DATABASE_USERNAME',
// password: 'DATABASE_PASSWORD',
// database: 'MAIN_DATABASE_NAME'
mysql: {
adapter: 'sails-mysql',
host: '127.0.0.1',
port: 3306,
user: 'myuser',
password: 'mypassword',
database: 'electron_release_server'
electron 自动更新之路总结(上)版本管理服务器
afeiqiang:
electron 自动更新之路总结(上)版本管理服务器
afeiqiang:
electron 自动更新之路总结(上)版本管理服务器
m0_67523500:
kafka 延时消息处理
zsj0310: