14

我有一个需要打印票的应用程序。每张票必须是唯一的。该应用程序是 Windows 窗体,完全用 C# 编写。对于我们的应用,我们使用的是三星 ML-2525 激光单色打印机。

流程基本上如下,操作员选择一个产品/票(这是唯一的),然后按下一个按钮来做两件事:

  1. 连接到数据库并根据使用情况更新产品
  2. 打印票证(使用 System.Drawing 和 GDI+ 完成)

由于某种原因,每隔一段时间,需要打印的图像不会发送到打印机。这是一个罕见的情况,但它发生了。

我尝试使用 Win32_Printer ( http://msdn.microsoft.com/en-us/library/Aa394363 ) 连接到打印机,但无法获取当前打印机的状态(在线、离线、碳粉不足、卡纸, ETC)。我只能检查打印机是否存在以及是否正确安装了纸张尺寸。我尝试了类似于以下的代码,但没有成功

    private string MonitorPrintJobWmi()
    {
        var jobMessage = String.Empty;
        var scope = new ManagementScope(ManagementPath.DefaultPath);
        scope.Connect();

        var selectQuery = new SelectQuery { QueryString = @"select *  from Win32_PrintJob" };

        var objSearcher = new ManagementObjectSearcher(scope, selectQuery);
        var objCollection = objSearcher.Get();

        foreach (var job in objCollection)
        {
            if (job != null)
            {
                jobMessage += String.Format("{0} \r\n", job["Name"].ToString());
                jobMessage += String.Format("{0} \r\n", job["JobId"].ToString());
                _jobId = Convert.ToInt32(job["JobId"]);
                jobMessage += String.Format("{0} \r\n", job["JobStatus"].ToString());
                jobMessage += String.Format("{0} \r\n", job["Status"].ToString());
            }
        }
        return jobMessage;
    }

我试图获取打印机的 API,但我无法掌握它。顺便说一句,打印机的软件确实会在 Windows 工具栏中显示不同的错误。

我的问题是,是否有人可以引导我了解如何连接打印机并检查打印是否成功。

另外,如果有人知道我可以在其中完成此操作的其他特定打印机(即更改硬件),那将很有帮助。

谢谢,

4

2 回答 2

5

要获取本地机器上的打印队列列表,请尝试 PrintServer 的GetPrintQueues方法。

一旦有了与相关打印机关联的PrintQueue对象的实例,就可以使用它来访问打印机的状态(IsOffline、IsPaperOut 等)。此外,您可以使用它来获取给定队列 ( GetPrintJobInfoCollection ) 中的作业列表,然后您可以获取特定于作业的状态信息(IsInError、IsCompleted、IsBlocked 等)。

希望这可以帮助!

于 2012-09-13T16:13:08.787 回答
0

尝试打印您的 PrintDocument (System.Drawing.Printing) 后,尝试检查打印作业的状态。

第一步:初始化你的 printDocument。

第二步:获取您的打印机名称System.Drawing.Printing.PrinterSettings.InstalledPrinters.Cast<string>();

并将其复制到您的打印机Document.PrinterSettings.PrinterName

第三步:尝试打印和处理。

printerDocument.Print();
printerDocument.Dispose();

最后一步:在任务中运行检查(不要阻塞 UI 线程)。

 Task.Run(()=>{
     if (!IsPrinterOk(printerDocument.PrinterSettings.PrinterName,checkTimeInMillisec))
     {
        // failed printing, do something...
     }
    });

这是实现:

    private bool IsPrinterOk(string name,int checkTimeInMillisec)
    {
        System.Collections.IList value = null;
        do
        {
            //checkTimeInMillisec should be between 2000 and 5000
            System.Threading.Thread.Sleep(checkTimeInMillisec);
            // or use Timer with Threading.Monitor instead of thread sleep

            using (System.Management.ManagementObjectSearcher searcher = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_PrintJob WHERE Name like '%" + name + "%'"))
            {
                value = null;

                if (searcher.Get().Count == 0) // Number of pending document.
                    return true; // return because we haven't got any pending document.
                else
                {
                    foreach (System.Management.ManagementObject printer in searcher.Get())
                    {
                        value = printer.Properties.Cast<System.Management.PropertyData>().Where(p => p.Name.Equals("Status")).Select(p => p.Value).ToList();
                        break; 
                    }
                }
            }
       }
       while (value.Contains("Printing") || value.Contains("UNKNOWN") || value.Contains("OK"));

       return value.Contains("Error") ? false : true;    
    }

祝你好运。

于 2017-03-09T23:15:13.830 回答