是否有.NET方法来枚举所有可用的网络打印机?

时间:2022-10-30 10:46:34

Is there a straightforward way to enumerate all visible network printers in .NET? Currently, I'm showing the PrintDialog to allow the user to select a printer. The problem with that is, local printers are displayed as well (along with XPS Document Writer and the like). If I can enumerate network printers myself, I can show a custom dialog with just those printers.

是否有一种直接的方法来枚举.NET中的所有可见网络打印机?目前,我正在显示PrintDialog以允许用户选择打印机。问题是,本地打印机也会显示(与XPS Document Writer等一起)。如果我可以自己枚举网络打印机,我可以只显示那些打印机的自定义对话框。

Thanks!!

5 个解决方案

#1


8  

found this code here

在这里找到了这段代码

 private void btnGetPrinters_Click(object sender, EventArgs e)
        {
// Use the ObjectQuery to get the list of configured printers
            System.Management.ObjectQuery oquery =
                new System.Management.ObjectQuery("SELECT * FROM Win32_Printer");

            System.Management.ManagementObjectSearcher mosearcher =
                new System.Management.ManagementObjectSearcher(oquery);

            System.Management.ManagementObjectCollection moc = mosearcher.Get();

            foreach (ManagementObject mo in moc)
            {
                System.Management.PropertyDataCollection pdc = mo.Properties;
                foreach (System.Management.PropertyData pd in pdc)
                {
                    if ((bool)mo["Network"])
                    {
                        cmbPrinters.Items.Add(mo[pd.Name]);
                    }
                }
            }

        }

Update:

"This API function can enumerate all network resources, including servers, workstations, printers, shares, remote directories etc."

“此API函数可以枚举所有网络资源,包括服务器,工作站,打印机,共享,远程目录等。”

http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=741&lngWId=10

#2


15  

  • Get the default printer from LocalPrintServer.DefaultPrintQueue
  • 从LocalPrintServer.DefaultPrintQueue获取默认打印机

  • Get the installed printers (from user's perspective) from PrinterSettings.InstalledPrinters
  • 从PrinterSettings.InstalledPrinters获取已安装的打印机(从用户的角度来看)

  • Enumerate through the list:
  • 列举清单:

  • Any printer beginning with \\ is a network printer - so get the queue with new PrintServer("\\UNCPATH").GetPrintQueue("QueueName")
  • 任何以\\开头的打印机都是网络打印机 - 因此请使用新的PrintServer(“\\ UNCPATH”)获取队列.GetPrintQueue(“QueueName”)

  • Any printer not beginning with \\ is a local printer so get it with LocalPrintServer.GetQueue("Name")
  • 任何不以\\开头的打印机都是本地打印机,所以使用LocalPrintServer.GetQueue(“名称”)获取它

  • You can see which is default by comparing FullName property.
  • 您可以通过比较FullName属性来查看哪个是默认值。

Note: a network printer can be the default printer from LocalPrintServer.DefaultPrintQueue, but not appear in LocalPrintServer.GetPrintQueues()

注意:网络打印机可以是LocalPrintServer.DefaultPrintQueue的默认打印机,但不会出现在LocalPrintServer.GetPrintQueues()中

    // get available printers
    LocalPrintServer printServer = new LocalPrintServer();
    PrintQueue defaultPrintQueue = printServer.DefaultPrintQueue;

    // get all printers installed (from the users perspective)he t
    var printerNames = PrinterSettings.InstalledPrinters;
    var availablePrinters = printerNames.Cast<string>().Select(printerName => 
    {
        var match = Regex.Match(printerName, @"(?<machine>\\\\.*?)\\(?<queue>.*)");
        PrintQueue queue;
        if (match.Success)
        {
            queue = new PrintServer(match.Groups["machine"].Value).GetPrintQueue(match.Groups["queue"].Value);
        }
        else
        {
            queue = printServer.GetPrintQueue(printerName);
        }

        var capabilities = queue.GetPrintCapabilities();
        return new AvailablePrinterInfo()
        {
            Name = printerName,
            Default = queue.FullName == defaultPrintQueue.FullName,
            Duplex = capabilities.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge),
            Color = capabilities.OutputColorCapability.Contains(OutputColor.Color)
        };
    }).ToArray();

    DefaultPrinter = AvailablePrinters.SingleOrDefault(x => x.Default);

#3


11  

using the new System.Printing API

使用新的System.Printing API

using (var printServer = new PrintServer(string.Format(@"\\{0}", PrinterServerName)))
{
    foreach (var queue in printServer.GetPrintQueues())
    {
        if (!queue.IsShared)
        {
            continue;
        }
        Debug.WriteLine(queue.Name);
     }
 }

#4


2  

PrinterSettiings.InstalledPrinters should give you the collection you want

PrinterSettiings.InstalledPrinters应该为您提供所需的集合

#5


2  

In another post(https://*.com/a/30758129/6513653) relationed to this one, Scott Chamberlain said "I do not believe there is anything in .NET that can do this, you will need to make a native call". After to try all the possible .NET resource, I think he is right. So, I started to investigate how ADD PRINTER dialog does your search. Using Wireshark, I found out that ADD PRINTER send at least two types of packages to all hosts in local network: two http/xml request to 3911 port and three SNMP requests. 是否有.NET方法来枚举所有可用的网络打印机? The first SNMP request is a get-next 1.3.6.1.2.1.43, which is Printer-MIB. The second one, is a get 1.3.6.1.4.1.2699.1.2.1.2.1.1.3 which is pmPrinterIEEE1284DeviceId from PRINTER-PORT-MONITOR-MIB. This is the most interest because is from ADD PRINTER take printer name. The third is a get 1.3.6.1.2.1.1.1.0, which is sysDescr from SNMP MIB-2 System. I do believe that the second SNMP request is enough to find most of network printers in local network, so I did this code. It works for Windows Form Application and it depends on SnmpSharpNet.

在与此相关的另一篇文章(https://*.com/a/30758129/6513653)中,Scott Chamberlain说:“我不相信.NET中有任何东西可以做到这一点,你需要拨打本地电话”。在尝试了所有可能的.NET资源之后,我认为他是对的。所以,我开始研究ADD PRINTER对话框如何进行搜索。使用Wireshark,我发现ADD PRINTER向本地网络中的所有主机发送至少两种类型的包:两个http / xml请求到3911端口和三个SNMP请求。第一个SNMP请求是get-next 1.3.6.1.2.1.43,它是Printer-MIB。第二个是得到1.3.6.1.4.1.2699.1.2.1.2.1.1.3,它是来自PRINTER-PORT-MONITOR-MIB的pmPrinterIEEE1284DeviceId。这是最感兴趣的,因为来自ADD PRINTER取打印机名称。第三个是获取1.3.6.1.2.1.1.1.0,它是来自SNMP MIB-2系统的sysDescr。我相信第二个SNMP请求足以找到本地网络中的大多数网络打印机,所以我做了这个代码。它适用于Windows窗体应用程序,它取决于SnmpSharpNet。

Edit: I'm using ARP Ping instead normal Ping to search active hosts in network. Link for an example project: ListNetworks C# Project

编辑:我正在使用ARP Ping而不是普通Ping来搜索网络中的活动主机。示例项目的链接:ListNetworks C#Project

#1


8  

found this code here

在这里找到了这段代码

 private void btnGetPrinters_Click(object sender, EventArgs e)
        {
// Use the ObjectQuery to get the list of configured printers
            System.Management.ObjectQuery oquery =
                new System.Management.ObjectQuery("SELECT * FROM Win32_Printer");

            System.Management.ManagementObjectSearcher mosearcher =
                new System.Management.ManagementObjectSearcher(oquery);

            System.Management.ManagementObjectCollection moc = mosearcher.Get();

            foreach (ManagementObject mo in moc)
            {
                System.Management.PropertyDataCollection pdc = mo.Properties;
                foreach (System.Management.PropertyData pd in pdc)
                {
                    if ((bool)mo["Network"])
                    {
                        cmbPrinters.Items.Add(mo[pd.Name]);
                    }
                }
            }

        }

Update:

"This API function can enumerate all network resources, including servers, workstations, printers, shares, remote directories etc."

“此API函数可以枚举所有网络资源,包括服务器,工作站,打印机,共享,远程目录等。”

http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=741&lngWId=10

#2


15  

  • Get the default printer from LocalPrintServer.DefaultPrintQueue
  • 从LocalPrintServer.DefaultPrintQueue获取默认打印机

  • Get the installed printers (from user's perspective) from PrinterSettings.InstalledPrinters
  • 从PrinterSettings.InstalledPrinters获取已安装的打印机(从用户的角度来看)

  • Enumerate through the list:
  • 列举清单:

  • Any printer beginning with \\ is a network printer - so get the queue with new PrintServer("\\UNCPATH").GetPrintQueue("QueueName")
  • 任何以\\开头的打印机都是网络打印机 - 因此请使用新的PrintServer(“\\ UNCPATH”)获取队列.GetPrintQueue(“QueueName”)

  • Any printer not beginning with \\ is a local printer so get it with LocalPrintServer.GetQueue("Name")
  • 任何不以\\开头的打印机都是本地打印机,所以使用LocalPrintServer.GetQueue(“名称”)获取它

  • You can see which is default by comparing FullName property.
  • 您可以通过比较FullName属性来查看哪个是默认值。

Note: a network printer can be the default printer from LocalPrintServer.DefaultPrintQueue, but not appear in LocalPrintServer.GetPrintQueues()

注意:网络打印机可以是LocalPrintServer.DefaultPrintQueue的默认打印机,但不会出现在LocalPrintServer.GetPrintQueues()中

    // get available printers
    LocalPrintServer printServer = new LocalPrintServer();
    PrintQueue defaultPrintQueue = printServer.DefaultPrintQueue;

    // get all printers installed (from the users perspective)he t
    var printerNames = PrinterSettings.InstalledPrinters;
    var availablePrinters = printerNames.Cast<string>().Select(printerName => 
    {
        var match = Regex.Match(printerName, @"(?<machine>\\\\.*?)\\(?<queue>.*)");
        PrintQueue queue;
        if (match.Success)
        {
            queue = new PrintServer(match.Groups["machine"].Value).GetPrintQueue(match.Groups["queue"].Value);
        }
        else
        {
            queue = printServer.GetPrintQueue(printerName);
        }

        var capabilities = queue.GetPrintCapabilities();
        return new AvailablePrinterInfo()
        {
            Name = printerName,
            Default = queue.FullName == defaultPrintQueue.FullName,
            Duplex = capabilities.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge),
            Color = capabilities.OutputColorCapability.Contains(OutputColor.Color)
        };
    }).ToArray();

    DefaultPrinter = AvailablePrinters.SingleOrDefault(x => x.Default);

#3


11  

using the new System.Printing API

使用新的System.Printing API

using (var printServer = new PrintServer(string.Format(@"\\{0}", PrinterServerName)))
{
    foreach (var queue in printServer.GetPrintQueues())
    {
        if (!queue.IsShared)
        {
            continue;
        }
        Debug.WriteLine(queue.Name);
     }
 }

#4


2  

PrinterSettiings.InstalledPrinters should give you the collection you want

PrinterSettiings.InstalledPrinters应该为您提供所需的集合

#5


2  

In another post(https://*.com/a/30758129/6513653) relationed to this one, Scott Chamberlain said "I do not believe there is anything in .NET that can do this, you will need to make a native call". After to try all the possible .NET resource, I think he is right. So, I started to investigate how ADD PRINTER dialog does your search. Using Wireshark, I found out that ADD PRINTER send at least two types of packages to all hosts in local network: two http/xml request to 3911 port and three SNMP requests. 是否有.NET方法来枚举所有可用的网络打印机? The first SNMP request is a get-next 1.3.6.1.2.1.43, which is Printer-MIB. The second one, is a get 1.3.6.1.4.1.2699.1.2.1.2.1.1.3 which is pmPrinterIEEE1284DeviceId from PRINTER-PORT-MONITOR-MIB. This is the most interest because is from ADD PRINTER take printer name. The third is a get 1.3.6.1.2.1.1.1.0, which is sysDescr from SNMP MIB-2 System. I do believe that the second SNMP request is enough to find most of network printers in local network, so I did this code. It works for Windows Form Application and it depends on SnmpSharpNet.

在与此相关的另一篇文章(https://*.com/a/30758129/6513653)中,Scott Chamberlain说:“我不相信.NET中有任何东西可以做到这一点,你需要拨打本地电话”。在尝试了所有可能的.NET资源之后,我认为他是对的。所以,我开始研究ADD PRINTER对话框如何进行搜索。使用Wireshark,我发现ADD PRINTER向本地网络中的所有主机发送至少两种类型的包:两个http / xml请求到3911端口和三个SNMP请求。第一个SNMP请求是get-next 1.3.6.1.2.1.43,它是Printer-MIB。第二个是得到1.3.6.1.4.1.2699.1.2.1.2.1.1.3,它是来自PRINTER-PORT-MONITOR-MIB的pmPrinterIEEE1284DeviceId。这是最感兴趣的,因为来自ADD PRINTER取打印机名称。第三个是获取1.3.6.1.2.1.1.1.0,它是来自SNMP MIB-2系统的sysDescr。我相信第二个SNMP请求足以找到本地网络中的大多数网络打印机,所以我做了这个代码。它适用于Windows窗体应用程序,它取决于SnmpSharpNet。

Edit: I'm using ARP Ping instead normal Ping to search active hosts in network. Link for an example project: ListNetworks C# Project

编辑:我正在使用ARP Ping而不是普通Ping来搜索网络中的活动主机。示例项目的链接:ListNetworks C#Project