简体   繁体   中英

Function VB.NET to C# conversion

I have an application that I need to print an Excel file to a specific printer other than the default printer.

In VB.NET I found a function online that allows me to do this.

xlApp.ActivePrinter = FindPrinter("PrinterName")

with the code for the FindPrinter function being

 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

In C# I have the code as this

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

But the line before the foreach loop is causing problems with the .EnumValues section as C# isn't sure what to do with this, same with the RegObj.GetStringValue inside of the for loop.

From what i can tell these values are just a part of the System.Object class in VB.NET, but i can't find a way to make them work in C#.

Thanks to everyone who takes the time to help me with this.

The exact error is 'object' does not contain a definition for 'EnumValues' and no accessible extension method 'EnumValues' accepting a first argument of type 'object' could be found.

No need to open the registry with 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;
}

A word-by-word translation would be something more like:

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

There are much better ways of doing whatever it is you're trying to do though, from PrinterSettings.InstalledPrinters , the LocalPrintServer class, to WMI. And even if you insist on using the registry yourself, there are much better ways than using COM like this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM