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

breezee 5月前 868

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

库文件: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();


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

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