Функция VB.NET преобразование в C#

#c# #vb.net

Вопрос:

У меня есть приложение, которое мне нужно распечатать файл Excel на определенном принтере, отличном от принтера по умолчанию.

В VB.NET Я нашел в Интернете функцию, которая позволяет мне это делать.

 xlApp.ActivePrinter = FindPrinter("PrinterName")  

с кодом для функции FindPrinter, являющейся

 Function FindPrinter(ByVal PrinterName As String) As String   Dim Arr As Object  Dim Device As Object  Dim Devices As Object  Dim Printer As String  Dim RegObj As Object  Dim RegValue As String  Const HKEY_CURRENT_USER = amp;H80000001   RegObj = GetObject("winmgmts:{impersonationLevel=impersonate}!\.rootdefault:StdRegProv")  RegObj.EnumValues(HKEY_CURRENT_USER, "SoftwareMicrosoftWindows NTCurrentVersionDevices", Devices, Arr)    For Each Device In Devices  RegObj.getstringvalue(HKEY_CURRENT_USER, "SoftwareMicrosoftWindows NTCurrentVersionDevices", Device, RegValue)  Printer = Device amp; " on " amp; Split(RegValue, ",")(1)  If InStr(1, Printer, PrinterName, vbTextCompare) gt; 0 Then  FindPrinter = Printer  Exit Function  End If  Next  End Function  

В C# у меня есть код, как это

 public string FindPrinter(string PrinterName)  {  string FindPrinterRet = default;  var Arr = default(object);  var Devices = default(object);  string Printer;  object RegObj;  var RegValue = default(string);   const int HKEY_CURRENT_USER = int.MinValue   0x00000001;  RegObj = Microsoft.VisualBasic.Interaction.GetObject(@"winmgmts:{impersonationLevel=impersonate}!\.rootdefault:StdRegProv");  RegObj.EnumValues(HKEY_CURRENT_USER, @"SoftwareMicrosoftWindows NTCurrentVersionDevices", Devices, Arr);   foreach (var Device in (IEnumerable)Devices)  {  RegObj.GetStringValue(HKEY_CURRENT_USER, @"SoftwareMicrosoftWindows NTCurrentVersionDevices", Device, RegValue);  Printer = Conversions.ToString(Operators.ConcatenateObject(Operators.ConcatenateObject(Device, " on "), Strings.Split(RegValue, ",")[1]));  if (Strings.InStr(1, Printer, PrinterName, Constants.vbTextCompare) gt; 0)  {  FindPrinterRet = Printer;  return FindPrinterRet;  }  }   return FindPrinterRet;  }  

Но строка перед циклом foreach вызывает проблемы с разделом .EnumValues, так как C# не знает, что с этим делать, то же самое с RegObj.GetStringValue внутри цикла for.

Из того, что я могу сказать, эти значения являются лишь частью Системы.Класс объектов в VB.NET, но я не могу найти способ заставить их работать на C#.

Спасибо всем, кто находит время, чтобы помочь мне в этом.

Точная ошибка заключается в том, что «объект» не содержит определения для «значений перечисления», и не удалось найти доступный метод расширения «Значения перечисления», принимающий первый аргумент типа «объект».

Комментарии:

1. Можете ли вы быть более конкретным, чем «создание проблем»?

2. Что означает возникновение проблем и не уверен, что с этим делать ? Вы получаете сообщение об ошибке? Если да, то каково точное, полное содержание этого сообщения?

3. «объект» не содержит определения для «значений перечисления», и не удалось найти доступного метода расширения «Значения перечисления», принимающего первый аргумент типа «объект».

4. Я бы попробовал dynamic RegObj; вместо object RegObj; (хотя это всего лишь предположение)

5. Вы пытались найти функцию поиска принтера, уже написанную на C#?

Ответ №1:

Дословный перевод был бы чем-то большим, чем:

 static string? FindPrinter(string PrinterName) {  const int HKEY_CURRENT_USER = int.MinValue   0x00000001;   dynamic regObj = Interaction.GetObject(@"winmgmts:{impersonationLevel=impersonate}!\.rootdefault:StdRegProv")!;  regObj!.EnumValues(HKEY_CURRENT_USER, @"SoftwareMicrosoftWindows NTCurrentVersionDevices", out dynamic devices, out dynamic arr);   foreach (var device in devices)  {  regObj.GetStringValue(HKEY_CURRENT_USER, @"SoftwareMicrosoftWindows NTCurrentVersionDevices", device, out dynamic value);  var printer = $"{device} on {value.Split(',')[1]}";  if (printer.Contains(PrinterName, StringComparison.OrdinalIgnoreCase))  return printer;  }   return null; }  

Однако есть гораздо лучшие способы сделать то, что вы пытаетесь сделать , от PrinterSettings.InstalledPrinters LocalPrintServer класса до WMI. И даже если вы настаиваете на том, чтобы использовать реестр самостоятельно, есть гораздо лучшие способы, чем использовать COM подобным образом.

Комментарии:

1. Спасибо! В итоге я использовал foreach (строковый принтер в системе. Рисование. Печатание. Наборы принтеров. Установленные принтеры) { если (принтер. Содержит(«Имя принтера»)) xlApp.ActivePrinter = принтер; } Намного проще и, кажется, работает. Еще раз спасибо

2. Вот и все, C# в целом делает вещи намного проще 🙂

Ответ №2:

Нет необходимости открывать реестр с помощью WMI.

 public string FindPrinter(string PrinterName) {   string subkey = "Software\Microsoft\Windows NT\CurrentVersion\Devices";   var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(subkey);  var printers = key.GetValueNames();  foreach(var printer in printers)  {  if (printer == PrinterName) {  return key.GetValue(printer);  }  }  return null; }