【问题标题】:How to Determine Which Printers are Connected using WMI如何确定使用 WMI 连接了哪些打印机
【发布时间】:2012-11-08 08:49:29
【问题描述】:

我一直在尝试找出一种方法来确定哪些已安装的打印机已“连接”。经过一番谷歌搜索后,我想我必须深入研究 WMI。

所以我建立了这个测试:

// Struct to store printer data in.
public struct MyPrinter 
{ 
    public string Availability; 
    public string ExtendedPrinterStatus; 
    public string Name; 
    public string PrinterStatus; 
    public string Status; 
    public string StatusInfo; 

    public MyPrinter(string a, string eps, string n, string ps, string s, string si) 
    { 
        Availability = a; 
        ExtendedPrinterStatus = eps; 
        Name = n; 
        PrinterStatus = ps; 
        Status = s; 
        StatusInfo = si; 
    } 
}


var installedPrinters = new string[numPrinters];
PrinterSettings.InstalledPrinters.CopyTo(installedPrinters, 0);

var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Printer"); 
var data = new List<MyPrinter>(); 

foreach (var printer in searcher.Get()) 
{ 
    if (installedPrinters.Contains(printer["Name"].ToString()))
    {
        var availability = (printer["Availability"] ?? "").ToString(); 
        var extendedPrinterStatus = (printer["ExtendedPrinterStatus"] ?? "").ToString(); 
        var name = (printer["Name"] ?? "").ToString(); 
        var printerStatus = (printer["PrinterStatus"] ?? "").ToString(); 
        var status = (printer["Status"] ?? "").ToString(); 
        var statusInfo = (printer["StatusInfo"] ?? "").ToString(); 

        data.Add(new MyPrinter(availability, extendedPrinterStatus, name, printerStatus, status, statusInfo)); 
    }
}

我有 6 台打印机,其中 2 台是网络打印机。我已在所有打印机连接的情况下运行此程序,所有结果如下所示:

Availability = "" // printer["Availability"] = null
ExtendedPrinterStatus = "2" // 2 = Unknown
Name = "{printer name here}"
PrinterStatus = "3" // 3 = Idle
Status = "Unknown"
StatusInfo = "" // Null

所以打印机之间的唯一区别是名称。 我再次运行脚本,但这次我断开了笔记本电脑与网络的连接。因此,在这种情况下,有 2 台打印机不再连接。

奇怪的是(对我来说),结果完全一样。

我运行此测试的原因是,找出我需要为我的案例使用哪个字段。

所以最后,我无法弄清楚如何确定打印机是否已连接。 所以我想要的是一种在 C# 中找出已安装 + 连接的打印机的方法。如果有办法在不使用 WMI 类的情况下做到这一点,我也可以,只要它有效。

【问题讨论】:

标签: c# .net printing wmi


【解决方案1】:

我和一位同事尝试了很多方法来解决这个问题,我们认为这很有效:

private string[] GetAvailablePrinters()
{
    var installedPrinters = new string[PrinterSettings.InstalledPrinters.Count];
    PrinterSettings.InstalledPrinters.CopyTo(installedPrinters, 0);

    var printers = new List<string>();
    var printServers = new List<string>();
    var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Printer");

    foreach (var printer in searcher.Get())
    {
        var serverName = @"\\" + printer["SystemName"].ToString().TrimStart('\\');
        if (!printServers.Contains(serverName))
            printServers.Add(serverName);
    }

    foreach (var printServer in printServers)
    {
        var server = new PrintServer(printServer);
        try
        {
            var queues = server.GetPrintQueues();
            printers.AddRange(queues.Select(q => q.Name));
        }
        catch (Exception)
        {
            // Handle exception correctly
        }
    }

    return printers.ToArray();
}

诀窍是当打印服务器不可用时,GetPrintQueues 会抛出一些特定的异常。通过仅添加不引发此类异常的打印机,我们可以获得所有已连接打印机的列表。这不会检查打印机是否打开/关闭,因为这实际上并不重要。如果关闭,文档只会被放入打印队列中,稍后可以打印。

我希望这可以帮助其他遇到此问题的人。

旁注: 我决定不捕获该特定异常的原因是因为我必须仅为该异常引用一个 dll。

【讨论】:

  • 这不是忽略异常的好理由。养成非常坏的习惯。
  • 我从未说过我“忽略”异常!
  • 我指的是空的Catch(Exception) 块。
  • 抱歉,在撰写本文时我没有对它做任何事情,因为那不是我的目标。当然,最后我并没有把它留空。
  • 读者阅读我们发布的代码。许多人会认为您的意思是忽略异常,并会复制该代码。我建议如果您不想在代码示例中演示异常处理,只需完全省略 try/catch。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
  • 2016-03-17
  • 1970-01-01
相关资源
最近更新 更多