I see references and hints that programmatically one can add a networked printer to a local computer using the ManagementClass and such. However I have not been able to find any actual tutorials on doing just this.
has anyone actually used the ManagementClass to do this?
I am doing this:
var connectionOption = new ConnectionOption();
var mgmScope = new ManagementScope("root\cimv2",connectionOptions);
var printerClass = new ManagementClass(mgmScope, new ManagementPath("Win32_Printer"),null);
var printerObj = printerClass.CreateInstance();
printerObj["DeviceID"] = prnName; //
printerObj["DriverName"] = drvName; // full path to driver
printerObj["PortName"] = "myTestPort:";
var options = new PutOptions {Type = PutType.UpdateOrCreate};
printerObj.Put(options);
All this does is create an error "Generic Failure"
I cant figure out what I am missing..... any help or thoughts about this would be appreciated.
I think I need to better explain what I am trying to do... when the printers needed are not tied to a print server, I need to: create a tcpip raw port, connect a printer via tcp/ip, install drivers, optionally set default.
I was hoping WMI could basically take care of all of this but it doesnt appear to be the case.
thanks!
In the Devices and Printers window click on Add a printer. Choose "Add a local printer or network printer with manual settings", then click Next. Select Create a new port and choose Standard TCP/IP Port, then click Next. Under Hostname or IP address: Type in the IP address of the printer you intend to connect to.
I spent almost the week on that issue! My target is a bit more complicated, I want to wrap the C# code in a WCF service called by a SharePoint Add-In, and this WCF service should call remotely the client to install the printers. Thus I tried hard with WMI. In the mean time, I managed to use rundll32 solution (which requires first to create the port), and also did a powershell variant, really the simplest:
$printerPort = "IP_"+ $printerIP
$printerName = "Xerox WorkCentre 6605DN PCL6"
Add-PrinterPort -Name $printerPort -PrinterHostAddress $printerIP
Add-PrinterDriver -Name $printerName
Add-Printer -Name $printerName -DriverName $printerName -PortName $printerPort
The really tricky part is to know the name of the printer, it should match the string in the INF file!
But back to C# solution: I created a class with printerName, printerIP and managementScope as attributes. And driverName = printerName
private string PrinterPortName
{
get { return "IP_" + printerIP; }
}
private void CreateManagementScope(string computerName)
{
var wmiConnectionOptions = new ConnectionOptions();
wmiConnectionOptions.Impersonation = ImpersonationLevel.Impersonate;
wmiConnectionOptions.Authentication = AuthenticationLevel.Default;
wmiConnectionOptions.EnablePrivileges = true; // required to load/install the driver.
// Supposed equivalent to VBScript objWMIService.Security_.Privileges.AddAsString "SeLoadDriverPrivilege", True
string path = "\\\\" + computerName + "\\root\\cimv2";
managementScope = new ManagementScope(path, wmiConnectionOptions);
managementScope.Connect();
}
private bool CheckPrinterPort()
{
//Query system for Operating System information
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_TCPIPPrinterPort");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(managementScope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
{
if (m["Name"].ToString() == PrinterPortName)
return true;
}
return false;
}
private bool CreatePrinterPort()
{
if (CheckPrinterPort())
return true;
var printerPortClass = new ManagementClass(managementScope, new ManagementPath("Win32_TCPIPPrinterPort"), new ObjectGetOptions());
printerPortClass.Get();
var newPrinterPort = printerPortClass.CreateInstance();
newPrinterPort.SetPropertyValue("Name", PrinterPortName);
newPrinterPort.SetPropertyValue("Protocol", 1);
newPrinterPort.SetPropertyValue("HostAddress", printerIP);
newPrinterPort.SetPropertyValue("PortNumber", 9100); // default=9100
newPrinterPort.SetPropertyValue("SNMPEnabled", false); // true?
newPrinterPort.Put();
return true;
}
private bool CreatePrinterDriver(string printerDriverFolderPath)
{
var endResult = false;
// Inspired from https://msdn.microsoft.com/en-us/library/aa384771%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
// and http://microsoft.public.win32.programmer.wmi.narkive.com/y5GB15iF/adding-printer-driver-using-system-management
string printerDriverInfPath = IOUtils.FindInfFile(printerDriverFolderPath);
var printerDriverClass = new ManagementClass(managementScope, new ManagementPath("Win32_PrinterDriver"), new ObjectGetOptions());
var printerDriver = printerDriverClass.CreateInstance();
printerDriver.SetPropertyValue("Name", driverName);
printerDriver.SetPropertyValue("FilePath", printerDriverFolderPath);
printerDriver.SetPropertyValue("InfName", printerDriverInfPath);
// Obtain in-parameters for the method
using (ManagementBaseObject inParams = printerDriverClass.GetMethodParameters("AddPrinterDriver"))
{
inParams["DriverInfo"] = printerDriver;
// Execute the method and obtain the return values.
using (ManagementBaseObject result = printerDriverClass.InvokeMethod("AddPrinterDriver", inParams, null))
{
// result["ReturnValue"]
uint errorCode = (uint)result.Properties["ReturnValue"].Value; // or directly result["ReturnValue"]
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms681386(v=vs.85).aspx
switch (errorCode)
{
case 0:
//Trace.TraceInformation("Successfully connected printer.");
endResult = true;
break;
case 5:
Trace.TraceError("Access Denied.");
break;
case 123:
Trace.TraceError("The filename, directory name, or volume label syntax is incorrect.");
break;
case 1801:
Trace.TraceError("Invalid Printer Name.");
break;
case 1930:
Trace.TraceError("Incompatible Printer Driver.");
break;
case 3019:
Trace.TraceError("The specified printer driver was not found on the system and needs to be downloaded.");
break;
}
}
}
return endResult;
}
private bool CreatePrinter()
{
var printerClass = new ManagementClass(managementScope, new ManagementPath("Win32_Printer"), new ObjectGetOptions());
printerClass.Get();
var printer = printerClass.CreateInstance();
printer.SetPropertyValue("DriverName", driverName);
printer.SetPropertyValue("PortName", PrinterPortName);
printer.SetPropertyValue("Name", printerName);
printer.SetPropertyValue("DeviceID", printerName);
printer.SetPropertyValue("Location", "Front Office");
printer.SetPropertyValue("Network", true);
printer.SetPropertyValue("Shared", false);
printer.Put();
return true;
}
private void InstallPrinterWMI(string printerDriverPath)
{
bool printePortCreated = false, printeDriverCreated = false, printeCreated = false;
try
{
printePortCreated = CreatePrinterPort();
printeDriverCreated = CreatePrinterDriver(printerDriverPath);
printeCreated = CreatePrinter();
}
catch (ManagementException err)
{
if (printePortCreated)
{
// RemovePort
}
Console.WriteLine("An error occurred while trying to execute the WMI method: " + err.Message);
}
}
finally install the driver. I still need further tests if its works on a clean Windows. Did many install/uninstall of the driver during my tests
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With