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.