Home > Software design >  Function VB.NET to C# conversion
Function VB.NET to C# conversion

Time:10-21

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.

CodePudding user response:

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

CodePudding user response:

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.

  • Related