#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; }