函数 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.InstalledPrintersLocalPrintServer class 到 WMI,无论您想做什么,都有更好的方法。而且即使您坚持自己使用注册表,也有比这样使用 COM 更好的方法。