2009-06-19 2 views
12

Есть ли простой способ перечислить все видимые сетевые принтеры в .NET? В настоящее время я показываю PrintDialog, чтобы разрешить пользователю выбирать принтер. Проблема заключается в том, что отображаются локальные принтеры (вместе с XPS Document Writer и т. П.). Если я могу самостоятельно перечислять сетевые принтеры, я могу показать пользовательский диалог только с этими принтерами.Есть ли способ .NET для перечисления всех доступных сетевых принтеров?

Спасибо!

+0

ДоступенPrinterInfo в каком пространстве имен? Получение как Ошибка Тип или имя пространства имен «AvailablePrinterInfo» не удалось найти (вам не хватает директивы использования или ссылки на сборку – 2011-11-03 07:42:00

ответ

8

нашел этот код 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:

«Эта функция API может перечислить все сетевые ресурсы, включая серверы, рабочие станции, принтеры, домены, удаленные каталоги и т. д. "

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

+0

+1 Спасибо, я могу перечислять только имена установленных сетевых принтеров с небольшими корректировками этого кода. Теперь вы знаете, могут перечислять все сетевые принтеры VISIBLE (а не только установленные) с использованием аналогичной методики. – Pwninstein

+0

попробуйте эту статью: http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=741&lngWId= 10 " Эта функция API может перечислять все сетевые ресурсы, включая серверы, рабочие станции, принтеры, общие папки, удаленные каталоги и т. Д. » Надеюсь, это поможет, приветствия –

+0

null исключение в последнем утверждении. –

2

PrinterSettiings.InstalledPrinters должно дать вам коллекцию, которую Вы хотите

+1

PrinterSettings.InstalledPrinters по-прежнему показывает, сетевые принтеры, а также принтеры документов (PDF Writer, XPS Document Writer и т. д.). – Pwninstein

9

с помощью нового API System.Printing

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

В этом списке перечислены только локальные принтеры, а не сетевые принтеры. – awe

+0

awe: попробуйте обновленный код – Simon

+0

Спасибо, это отлично сработало для того, что мне нужно +1 –

13
  • Получить принтер по умолчанию из LocalPrintServer.DefaultPrintQueue
  • Получить установленные принтеры (с точки зрения пользователя) от PrinterSettings.InstalledPrinters
  • Перечислить через список:
  • Любой принтер, начиная с \\ является сетевым принтером - так получите очередь с new PrintServer("\\UNCPATH").GetPrintQueue("QueueName")
  • Любой принтер не начиная с \\ является локальный принтер поэтому получить его с LocalPrintServer.GetQueue("Name")
  • Вы можете увидеть, что по умолчанию путем сравнения FullName свойства.

Примечание: сетевой принтер может быть принтером по умолчанию из 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); 
+0

Спасибо Simon - очень полезно. – PolicyWatcher

1

В другом посте (https://stackoverflow.com/a/30758129/6513653) relationed к этому, Скотт Чемберлен сказал: «Я не верю в .NET есть что-то, что можно сделать, вам нужно будет сделать собственный вызов ». После того, как попробовать все возможные ресурсы .NET, я думаю, что он прав. Итак, я начал исследовать, как диалог ADD PRINTER выполняет поиск. Используя Wireshark, я узнал, что ADD PRINTER отправляет по крайней мере два типа пакетов всем хостам в локальной сети: два запроса http/xml для порта 3911 и три запроса SNMP. enter image description here Первый запрос SNMP - это получение следующего 1.3.6.1.2.1.43, которое является Printer-MIB. Второй - это получить 1.3.6.1.4.1.2699.1.2.1.2.1.1.3, который является pmPrinterIEEE1284DeviceId из PRINTER-PORT-MONITOR-MIB. Это больше всего интересует, потому что от ADD PRINTER берет имя принтера. Третий - это получить 1.3.6.1.2.1.1.1.0, который является sysDescr из системы SNMP MIB-2. Я действительно верю, что второго запроса SNMP достаточно, чтобы найти большинство сетевых принтеров в локальной сети, поэтому я сделал этот код. Он работает для Windows Form Application, и это зависит от SnmpSharpNet.

Редактировать: Я использую ARP Ping вместо обычного Ping для поиска активных хостов в сети.Ссылка на пример проекта: ListNetworks C# Project

Смежные вопросы