最近用aardio写了一个打印管理工具,写了一个简单的库,实现了简单的打印机和打印任务管理功能,分享给大家一起学习。
![](https://aar.chengxu.online/upload/files/20240608/1717839745.png)
库文件:printMGT
//Printer MGT
//打印机控制 by breezee
//https://blog.csdn.net/wuyindesign/article/details/139549307
namespace printMGT;
import com.wmi;
//获取所有打印机
getAllPrinter = function() {
//返回数据结构:
//{name=打印机名, status=打印机状态, portName=端口名}
var getPrinterStatus = function(statusCode) { //返回打印机状态
select(statusCode) {
case 1 return "其他"
case 2 return "未知"
case 3 return "空闲"
case 4 return "正在打印"
case 5 return "预热"
case 6 return "停止打印"
case 7 return "脱机"
else return "错误"
}
}
var prtList = {};
//https://learn.microsoft.com/zh-cn/windows/win32/cimwin32prov/win32-printer?redirectedfrom=MSDN
//https://wutils.com/wmi/root/cimv2/win32_printer/
//DeviceID 系统上打印机的唯一标识符, PortName 端口, PrinterState 打印机的状态信息与逻辑设备
for index, wmiPrinter in com.wmi.each("SELECT * FROM Win32_Printer") {
..table.push( prtList, {name = wmiPrinter.Name; status = wmiPrinter.WorkOffline?"脱机":getPrinterStatus(wmiPrinter.PrinterStatus), portName = wmiPrinter.PortName}); //打印机名称,打印机状态:就绪/脱机/正在打印
}
return prtList;
}
//获取打印任务
getPrintQueue = function(printerName) { //如果没有指定打印机,则读取所有打印任务
//返回数据结构:
//{name="打印机名称";jobs={{"文档名","状态","所有者","页数","文档大小","纸张大小","提交时间","端口","优先级","任务ID","打印机名称"}}}
var jobs = {};
for index, wmiJob in com.wmi.each("SELECT * FROM Win32_PrintJob") {
//Name 打印机名+作业的标识符号; DriverName 用于打印作业的打印机驱动程序的名称;
//JobId 作业的标识符; JobStatus 作业状态; Status 对象的当前状态; StatusMask 与此打印作业相关的可能状态的掩码
//StartTime 作业开始的时间, ElapsedTime 作业执行的时间长度, TimeSubmitted 提交作业的时间, UntilTime 作业无效或应停止的时间
//Document 打印作业的名称; DriverName 打印作业的驱动名称;
//ElapsedTime 作业执行的时间长度; StartTime 作业开始的时间; TimeSubmitted 提交作业的时间;
//PagesPrinted 打印的页数。 如果打印作业不包含分页分隔信息,则此值可以为 0
//TotalPages 完成作业所需的页数; UntilTime 作业无效或应停止的时间; Priority 优先级;
//var printer = {name = wmiPrinter.Name; status = wmiPrinter.WorkOffline?"脱机":getPrinterStatus(wmiPrinter.PrinterStatus)}
var prtName = ..string.split(wmiJob.Name, ",")[1];
if (#printerName && prtName != printerName) continue;
var jobInfo = {};
..table.push(jobInfo, wmiJob.Document, wmiJob.JobStatus?wmiJob.JobStatus:"-", wmiJob.Owner); //文档名 状态 所有者
if (wmiJob.PagesPrinted == 0) //已打印页数/文档总页数
..table.push(jobInfo, wmiJob.TotalPages)
else ..table.push(jobInfo, wmiJob.PagesPrinted ++ "/" ++ (wmiJob.PagesPrinted + wmiJob.TotalPages));
if (wmiJob.Size >= 1024*1024) //文档大小
..table.push(jobInfo, ..math.floor(wmiJob.Size/1048576) ++ " MB")
else ..table.push(jobInfo, ..math.floor(wmiJob.Size/1024) ++ " KB");
..table.push(jobInfo, wmiJob.PaperSize); //纸张大小
var y,m,d,h,min,s = ..string.match(wmiJob.TimeSubmitted, "^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})");
..table.push(jobInfo, ..string.format("%d:%d:%d %d/%d/%d",h,min,s,y,m,d)); //提交时间
..table.push(jobInfo, ""); //端口号
..table.push(jobInfo, wmiJob.Priority); //优先级
..table.push(jobInfo, wmiJob.JobId); //作业的标识符
if (!jobs[prtName]) jobs[prtName] = {};
..table.push(jobs[prtName], jobInfo);
}
var prtQueue = {};
for(name, value in jobs){
..table.push(prtQueue, {name=name, jobs=value});
}
return prtQueue;
}
//根据任务ID返回任务对象
getPrintJob = function(jobID){
if (!jobID) return;
var job;
for index, wmiJob in com.wmi.each("SELECT * FROM Win32_PrintJob WHERE JobId=" ++ jobID) {
job = wmiJob;
}
return job;
}
//取消打印任务
cancelPrintJob = function(jobID){
var job = getPrintJob(jobID);
if (job) job.Delete_(); //后面带下划线的是隐藏方法
}
//打开系统设置面板:打印机和扫描仪
openPrintersAndFaxesFolder = function(){
import process.control;
if(!_WIN10_LATER){
//更多设置页面地址参数:https://learn.microsoft.com/zh-cn/windows/uwp/launch-resume/launch-settings-app#devices
process.control("ms-settings:printers")
}
else {
//控制面板\所有控制面板项\设备和打印机
process.control("printers")
}
}
//打开打印队列对话框
openPrinterQueue = function(prtName){
if (!prtName) return;
import process.rundll;
process.rundll("printui.dll","PrintUIEntry",'/o /n "' ++ prtName ++ '"');
}
//打开打印机首选项
openPrinterPreferences = function(prtName){
if (!prtName) return;
import process.rundll;
process.rundll("printui.dll","PrintUIEntry",'/e /n "' ++ prtName ++ '"');
}
//打开打印机属性对话框
openPrintProperties = function(prtName){
if (!prtName) return;
import process.rundll;
process.rundll("printui.dll","PrintUIEntry",'/p /n "' ++ prtName ++ '"');
}
使用示例:
import win.ui;
import fonts.fontAwesome;
/*DSG{{*/
winform = win.form(text="打印管理 - by breezee";right=1151;bottom=543)
winform.add(
btnLoadPrinter={cls="button";text="加载所有打印机";left=16;top=16;right=151;bottom=56;z=1};
btnPrintersFolder={cls="button";text="打开设备和打印机";left=1008;top=24;right=1136;bottom=56;color=8421504;z=3};
lvwPrintJob={cls="listview";left=16;top=320;right=1136;bottom=528;edge=1;fullRow=1;msel=false;z=5};
lvwPrinter={cls="listview";left=16;top=72;right=1136;bottom=280;edge=1;fullRow=1;msel=false;z=4};
static2={cls="static";text="打印任务:";left=16;top=296;right=120;bottom=320;color=8421504;db=1;dl=1;font=LOGFONT(h=-15);transparent=1;z=6};
staticPrinter={cls="static";left=96;top=296;right=600;bottom=320;db=1;dl=1;font=LOGFONT(h=-15);transparent=1;z=2};
staticTotal={cls="static";left=632;top=296;right=1136;bottom=320;align="right";color=8421504;db=1;dl=1;transparent=1;z=7}
)
/*}}*/
//打印机控制 by breezee
//
import console;
import printMGT;
//加载打印机按钮
winform.btnLoadPrinter.oncommand = function(id,event) {
//读取所有打印机列表(包含脱机的)
winform.lvwPrinter.clear();
var printerList = printMGT.getAllPrinter();
for (i=1; #printerList; 1) {
winform.lvwPrinter.addItem({printerList[i].name; printerList[i].portName; printerList[i].status});
}
}
//打开系统控制面板:设备和打印机
winform.btnPrintersFolder.oncommand = function(id,event){
printMGT.openPrintersAndFaxesFolder();
}
//打印机列表
winform.lvwPrinter.setColumns({"打印机名称","端口名称","状态"},{300,350,80});
winform.lvwPrinter.onFocusedChanged = function(item,subItem,nmListView){
var prtName = owner.getItemText(item,subItem);
winform.staticPrinter.text = prtName;
winform.staticTotal.text = "";
winform.lvwPrintJob.clear();
var printQueue = printMGT.getPrintQueue(prtName); //获取该打印机的打印队列
if (#printQueue) {
winform.staticTotal.text = "队列中有 " ++ #printQueue ++ " 个文档"
for(i=1; #printQueue[1].jobs; 1){
winform.lvwPrintJob.addItem(printQueue[1].jobs[i]);
}
}
}
//打印机列表右键菜单
winform.lvwPrinter.onRightClick = function(item,subItem,nmListView){
if (!item) return;
import win.ui.menu;
var popmenu = win.ui.popmenu(winform);
popmenu.add("打印机属性",,,1);
popmenu.add("打印首选项",,,2);
popmenu.add("打开打印队列",,,3);
var ptrName = owner.getItemText(item,1);
if (#ptrName) {
select(popmenu.popId()) {
case 1 printMGT.openPrintProperties(ptrName);
case 2 printMGT.openPrinterPreferences(ptrName);
case 3 printMGT.openPrinterQueue(ptrName);
}
}
}
//打印队列列表
winform.lvwPrintJob.setColumns({"文档名","状态","所有者","页数","文档大小","纸张大小","提交时间","端口","优先级","任务ID"},{300,150,80,50,80,130,130,50,60,0});
//打印队列右键菜单
winform.lvwPrintJob.onRightClick = function(item,subItem,nmListView){
if (!item) return;
var jobId = owner.getItemText(item, 10);
var job = printMGT.getPrintJob(jobId); //获取打印任务
if (!job) {
import win.dlg.message;
winform.msgErr("加载该打印任务出错。");
return;
}
var jobStatus = job.JobStatus : "-"; //任务状态
//创建右键菜单
import win.ui.menu;
var popmenu = win.ui.popmenu(winform);
if (string.find(jobStatus, "暂停"))
popmenu.add("继续",,,1)
else
popmenu.add("暂停",,,1);
popmenu.add("重新启动",,,2);
popmenu.add(/*---分隔线---*/);
popmenu.add("取消任务",,,3);
popmenu.add(/*---分隔线---*/);
popmenu.add("任务属性",,,4);
popmenu.enable(6,false); //暂时未能实现"任务属性"
select(popmenu.popId()) {
case 1 { //暂停
if (job){
if (string.find(jobStatus, "暂停"))
job.Resume() //继续
else
job.Pause(); //暂停
//更新任务状态
job = printMGT.getPrintJob(jobId);
owner.setItemText(job.JobStatus:"-", item, 2);
}
}
case 2 { //重新启动
printMGT.openPrinterProperties(winform.staticPrinter.text);
}
case 3 { //取消任务
printMGT.cancelPrintJob(jobId);
owner.delItem(item);
}
case 4 { //任务属性
//暂时没有实现"任务属性"
}
}
}
winform.show();
return win.loopMessage();