用aardio管理打印机及打印任务

breezee 10月前 1367

最近用aardio写了一个打印管理工具,写了一个简单的库,实现了简单的打印机和打印任务管理功能,分享给大家一起学习。

库文件:printMGT

Code AardioLine:131复制
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
    • //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 ++ '"');
    • }

    使用示例:

    Code AardioLine:125复制
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
    • 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();


    最新回复 (5)
    • 光庆 10月前
      1 2

    • ftgli 8月前
      0 3
      不错,不知道能不能做成打印调度呢?
    • breezee 8月前
      0 4
      ftgli 不错,不知道能不能做成打印调度呢?
      不知道打印调度是什么,这里调用的都是WMI的功能
    • ftgli 8月前
      0 5
      breezee 不知道打印调度是什么,这里调用的都是WMI的功能
      就是多台打印机分配打印任务那种
    • breezee 8月前
      0 6
      ftgli 就是多台打印机分配打印任务那种
      简单的打印任务应该是可以的,在软件里选择需要打印的文档,然后根据一定规则分配给不同的打印机。单前提是要先设置好各个打印机的默认打印选项,才好实施无人值守自动打印。另外,好像也可以打印前给打印机加载指定打印配置的功能,基本上都可以通过WMI实现。
    返回