使用C#(系统范围)

时间:2015-08-13 08:39:06

标签: c# windows winapi com print-spooler-api

我已经接受了将近2天,我还没有做任何事情! 我被指派编写一个程序来计算在Windows OS上打印的页数 据我所知,我需要拦截打印事件并在内部对它们进行计数。我应该使用FindFirstPrinterChangeNotificationFindNextPrinterChangeNotification

我已经分配了一个带有以下签名的回调函数PrinterNotifyWaitCallback,当打印事件发生时,它会多次触发

 public void PrinterNotifyWaitCallback(Object state, bool timedOut) { ... }

问题:

我对打印事件为何多次触发PrinterNotifyWaitCallback 但是有一些线索我无法区分这些多次回调中的实际打印回调事件,这显然与Object state有关,但没有关于如何实现我的目标的文件,即计算打印页面。

的问题:

  1. 如何区分PrinterNotifyWaitCallback的实际打印回调以计算总打印页数系统范围
  2. 还有其他更好的方法可以完成任务吗?

1 个答案:

答案 0 :(得分:0)

我大致通过WMI找到了解决方案。为了它的价值,我想出了以下来计算打印页面。

lock (this._printStatusLast)
{
    // make a query to OS
    // TODO: make the printers exclude from counting in below query (defined by admin)
    ManagementObjectCollection pmoc = new ManagementObjectSearcher("SELECT Name, NotReadyErrors, OutofPaperErrors, TotalJobsPrinted, TotalPagesPrinted FROM Win32_PerfRawData_Spooler_PrintQueue").Get();
    Dictionary<String, PrintDetail> phs = new Dictionary<string, PrintDetail>();
    foreach (ManagementObject mo in pmoc)
    {
        // do not count everything twice!! (this is needed to for future developments on excluding printers from getting count)
        if (mo["name"].ToString().ToLower() == "_total") continue;
        PrintDetail pd = new PrintDetail();
        foreach (PropertyData prop in mo.Properties)
        {
            if (prop.Name.ToLower() == "name") continue;
            pd[prop.Name] = (UInt32)prop.Value;
        }
        phs.Add(mo["name"].ToString(), pd);
    }
    UInt32 count = 0;
    // foreach category
    foreach (var _key in phs.Keys.ToArray<String>())
    {
        // do not count if there where any errors
        if (phs[_key].HasError) continue;
        count += phs[_key].TotalPagesPrinted;
    }
    this.txtPrint.Text = count.ToString();
    this._printStatusLast = new Dictionary<string, PrintDetail>(phs);
}