函数 VB.NET 到 C# 的转换
Function VB.NET to C# conversion
我有一个应用程序需要将 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 = &H80000001
RegObj = GetObject("winmgmts:{impersonationLevel=impersonate}!\.\root\default:StdRegProv")
RegObj.EnumValues(HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", Devices, Arr)
For Each Device In Devices
RegObj.getstringvalue(HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", Device, RegValue)
Printer = Device & " on " & Split(RegValue, ",")(1)
If InStr(1, Printer, PrinterName, vbTextCompare) > 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}!\.\root\default:StdRegProv");
RegObj.EnumValues(HKEY_CURRENT_USER, @"Software\Microsoft\Windows NT\CurrentVersion\Devices", Devices, Arr);
foreach (var Device in (IEnumerable)Devices)
{
RegObj.GetStringValue(HKEY_CURRENT_USER, @"Software\Microsoft\Windows NT\CurrentVersion\Devices", Device, RegValue);
Printer = Conversions.ToString(Operators.ConcatenateObject(Operators.ConcatenateObject(Device, " on "), Strings.Split(RegValue, ",")[1]));
if (Strings.InStr(1, Printer, PrinterName, Constants.vbTextCompare) > 0)
{
FindPrinterRet = Printer;
return FindPrinterRet;
}
}
return FindPrinterRet;
}
但是 foreach 循环之前的行导致 .EnumValues 部分出现问题,因为 C# 不确定如何处理它,与 for 循环内部的 RegObj.GetStringValue 相同。
据我所知,这些值只是 VB.NET 中 System.Object class 的一部分,但我找不到让它们在 C# 中工作的方法。
感谢所有花时间帮助我的人。
确切的错误是
'object' 不包含 'EnumValues' 的定义,并且找不到接受类型 'object' 的第一个参数的可访问扩展方法 'EnumValues'。
不需要用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;
}
逐字翻译更像是:
static string? FindPrinter(string PrinterName)
{
const int HKEY_CURRENT_USER = int.MinValue + 0x00000001;
dynamic regObj = Interaction.GetObject(@"winmgmts:{impersonationLevel=impersonate}!\.\root\default:StdRegProv")!;
regObj!.EnumValues(HKEY_CURRENT_USER, @"Software\Microsoft\Windows NT\CurrentVersion\Devices", out dynamic devices, out dynamic arr);
foreach (var device in devices)
{
regObj.GetStringValue(HKEY_CURRENT_USER, @"Software\Microsoft\Windows NT\CurrentVersion\Devices", device, out dynamic value);
var printer = $"{device} on {value.Split(',')[1]}";
if (printer.Contains(PrinterName, StringComparison.OrdinalIgnoreCase))
return printer;
}
return null;
}
不过,从 PrinterSettings.InstalledPrinters
、LocalPrintServer
class 到 WMI,无论您想做什么,都有更好的方法。而且即使您坚持自己使用注册表,也有比这样使用 COM 更好的方法。
我有一个应用程序需要将 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 = &H80000001
RegObj = GetObject("winmgmts:{impersonationLevel=impersonate}!\.\root\default:StdRegProv")
RegObj.EnumValues(HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", Devices, Arr)
For Each Device In Devices
RegObj.getstringvalue(HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", Device, RegValue)
Printer = Device & " on " & Split(RegValue, ",")(1)
If InStr(1, Printer, PrinterName, vbTextCompare) > 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}!\.\root\default:StdRegProv");
RegObj.EnumValues(HKEY_CURRENT_USER, @"Software\Microsoft\Windows NT\CurrentVersion\Devices", Devices, Arr);
foreach (var Device in (IEnumerable)Devices)
{
RegObj.GetStringValue(HKEY_CURRENT_USER, @"Software\Microsoft\Windows NT\CurrentVersion\Devices", Device, RegValue);
Printer = Conversions.ToString(Operators.ConcatenateObject(Operators.ConcatenateObject(Device, " on "), Strings.Split(RegValue, ",")[1]));
if (Strings.InStr(1, Printer, PrinterName, Constants.vbTextCompare) > 0)
{
FindPrinterRet = Printer;
return FindPrinterRet;
}
}
return FindPrinterRet;
}
但是 foreach 循环之前的行导致 .EnumValues 部分出现问题,因为 C# 不确定如何处理它,与 for 循环内部的 RegObj.GetStringValue 相同。
据我所知,这些值只是 VB.NET 中 System.Object class 的一部分,但我找不到让它们在 C# 中工作的方法。
感谢所有花时间帮助我的人。
确切的错误是 'object' 不包含 'EnumValues' 的定义,并且找不到接受类型 'object' 的第一个参数的可访问扩展方法 'EnumValues'。
不需要用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;
}
逐字翻译更像是:
static string? FindPrinter(string PrinterName)
{
const int HKEY_CURRENT_USER = int.MinValue + 0x00000001;
dynamic regObj = Interaction.GetObject(@"winmgmts:{impersonationLevel=impersonate}!\.\root\default:StdRegProv")!;
regObj!.EnumValues(HKEY_CURRENT_USER, @"Software\Microsoft\Windows NT\CurrentVersion\Devices", out dynamic devices, out dynamic arr);
foreach (var device in devices)
{
regObj.GetStringValue(HKEY_CURRENT_USER, @"Software\Microsoft\Windows NT\CurrentVersion\Devices", device, out dynamic value);
var printer = $"{device} on {value.Split(',')[1]}";
if (printer.Contains(PrinterName, StringComparison.OrdinalIgnoreCase))
return printer;
}
return null;
}
不过,从 PrinterSettings.InstalledPrinters
、LocalPrintServer
class 到 WMI,无论您想做什么,都有更好的方法。而且即使您坚持自己使用注册表,也有比这样使用 COM 更好的方法。