使用ManagementClass将打印机添加到本地计算机

我看到参考和提示,以编程方式可以使用ManagementClass等将网络打印机添加到本地计算机。 但是我还没有找到任何有关这方面的实际教程。

有没有人实际使用过ManagementClass呢?

我这样做:

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

所有这一切都是创建一个错误“通用失败”

我无法弄清楚我错过了什么…..任何有关这方面的帮助或想法将不胜感激。

我想我需要更好地解释我想要做什么…当打印机需要的打印机没有绑定时,我需要:创建一个tcpip原始端口,通过tcp / ip连接打印机,安装驱动程序,可选默认设置。

我希望WMI能够基本上处理所有这些,但似乎并非如此。

谢谢!

WMI Win32_Printer类提供了一个名为AddPrinterConnection的方法,用于将网络打印机添加到本地打印机列表中。 下面的代码显示了如何使用Win32_Printer类连接网络打印机。

请注意,在某些情况下, AddPrinterConnection无法连接远程打印机。 在下面的示例中,我列出了最常见的错误情况。

 using (ManagementClass win32Printer = new ManagementClass("Win32_Printer")) { using (ManagementBaseObject inputParam = win32Printer.GetMethodParameters("AddPrinterConnection")) { // Replace  and  with the actual server and // printer names. inputParam.SetPropertyValue("Name", "\\\\\\"); using (ManagementBaseObject result = (ManagementBaseObject)win32Printer.InvokeMethod("AddPrinterConnection", inputParam, null)) { uint errorCode = (uint)result.Properties["returnValue"].Value; switch (errorCode) { case 0: Console.Out.WriteLine("Successfully connected printer."); break; case 5: Console.Out.WriteLine("Access Denied."); break; case 123: Console.Out.WriteLine("The filename, directory name, or volume label syntax is incorrect."); break; case 1801: Console.Out.WriteLine("Invalid Printer Name."); break; case 1930: Console.Out.WriteLine("Incompatible Printer Driver."); break; case 3019: Console.Out.WriteLine("The specified printer driver was not found on the system and needs to be downloaded."); break; } } } } 

为了做到这一点,我最终不得不做一个2步…

首先建立一个命令行来触发:

 rundll32.exe printui.dll,PrintUIEntry /if /b "test" /f x2DSPYP.inf /r 10.5.43.32 /m "845 PS" 

然后产卵:

  public static string ShellProcessCommandLine(string cmdLineArgs,string path) { var sb = new StringBuilder(); var pSpawn = new Process { StartInfo = { WorkingDirectory = path, FileName = "cmd.exe", CreateNoWindow = true, Arguments = cmdLineArgs, RedirectStandardInput = true, RedirectStandardOutput = true, UseShellExecute = false } }; pSpawn.OutputDataReceived += (sender, args) => sb.AppendLine(args.Data); pSpawn.Start(); pSpawn.BeginOutputReadLine(); pSpawn.WaitForExit(); return sb.ToString(); } 

这似乎工作…不是理想的方法,但对于那些不在打印服务器上的打印机,它似乎可以完成这项工作。

我在这个问题上花了差不多一周的时间! 我的目标有点复杂,我想将C#代码包装在SharePoint外接程序调用的WCF服务中,并且此WCF服务应远程调用客户端来安装打印机。 因此,我努力与WMI。 与此同时,我设法使用rundll32解决方案(首先需要创建端口),并且还做了一个powershell变体,真的是最简单的:

 $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 

真正棘手的部分是知道打印机的名称,它应该匹配INF文件中的字符串!

但回到C#解决方案:我创建了一个以printerName,printerIP和managementScope作为属性的类。 并且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); } } 

最后安装驱动程序。 如果它在干净的Windows上工作,我还需要进一步测试。 我的测试期间有很多安装/卸载驱动程序

我想添加答案,因为还有另一种方法,Microsoft建议现在通过System.Management使用Microsoft.Management.Infrastructure。

以下是Microsoft文档的链接: https : //msdn.microsoft.com/en-us/library/microsoft.management.infrastructure.aspx

请注意,您必须在c#project中添加对Microsoft.Management.Infrastructure dll的引用: Microsoft.Management.Infrastructure的位置

您可能还需要在计算机上配置winrm https://docs.microsoft.com/en-us/windows/desktop/winrm/installation-and-configuration-for-windows-remote-management

以下是使用c#从打印服务器向本地计算机添加打印机的示例代码

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Management.Infrastructure; using Microsoft.Management.Infrastructure.Generic; using Microsoft.Management.Infrastructure.Options; namespace MMITest { class Program { static void Main(string[] args) { using (var session = CimSession.Create("localhost")) { using (var cimMethodParameters = new CimMethodParametersCollection()) { cimMethodParameters.Add(CimMethodParameter.Create("Name", @"\\PrintServerName\PrinterName", CimFlags.Parameter)); session.InvokeMethod(@"root\cimv2", "Win32_Printer", "AddPrinterConnection", cimMethodParameters); } } Console.ReadLine(); } } 

}