C# 是否有一种 .NET 方法来枚举所有可用的网络打印机?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1018001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a .NET way to enumerate all available network printers?
提问by Mark Carpenter
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!!
谢谢!!
采纳答案by Andrija
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
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=741&lngWId=10
回答by Robert
PrinterSettiings.InstalledPrinters
should give you the collection you want
PrinterSettiings.InstalledPrinters
应该给你你想要的集合
回答by Simon
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);
}
}
回答by Simon_Weaver
- Get the default printer from
LocalPrintServer.DefaultPrintQueue
- Get the installed printers (from user's perspective) from
PrinterSettings.InstalledPrinters
- Enumerate through the list:
- Any printer beginning with
\\
is a network printer - so get the queue withnew PrintServer("\\UNCPATH").GetPrintQueue("QueueName")
- Any printer not beginning with
\\
is a local printer so get it withLocalPrintServer.GetQueue("Name")
- You can see which is default by comparing
FullName
property.
- 获取默认打印机
LocalPrintServer.DefaultPrintQueue
- 从以下位置获取已安装的打印机(从用户的角度)
PrinterSettings.InstalledPrinters
- 通过列表枚举:
- 任何以 开头的打印机
\\
都是网络打印机 - 所以用new PrintServer("\\UNCPATH").GetPrintQueue("QueueName")
- 任何不以 开头的打印机
\\
都是本地打印机,因此请使用LocalPrintServer.GetQueue("Name")
- 您可以通过比较
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);
回答by ViniCoder
In another post(https://stackoverflow.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 its 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. 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 of PRINTER-PORT-MONITOR-MIB. This is the most interesting because is where ADD PRINTER takes printer name. The third is a get 1.3.6.1.2.1.1.1.0, which is sysDescr of 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://stackoverflow.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。第二个是 get 1.3.6.1.4.1.2699.1.2.1.2.1.1.3,它是 PRINTER-PORT-MONITOR-MIB 的 pmPrinterIEEE1284DeviceId。这是最有趣的,因为这是 ADD PRINTER 取打印机名称的地方。第三个是get 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# 项目
回答by Underground
Note that if you're working over RDP it seems to complicate this because it looks like it just exports everything on the host as a local printer.
请注意,如果您在 RDP 上工作,这似乎会使情况复杂化,因为它看起来只是将主机上的所有内容导出为本地打印机。
Which is then a problem if you're expecting it to work the same way when not on RDP.
如果您希望它在不使用 RDP 时以相同的方式工作,那么这就是一个问题。