如何在 C# 中删除网络打印机连接
How do I remove a network printer connection in c#
我的最终目标是取消映射本地工作站上的特定网络打印机。我已经尝试通过 WMI、Windows 脚本宿主和 Winspool.drv Win32 API。我对任何方向的想法都持开放态度。
当使用 WMI 时,我有以下简化的函数,大部分是从 http://www.codeproject.com/Articles/80680/Managing-Printers-Programatically-using-C-and-WMI 复制的:
public void unmapPrinter()
{
ManagementClass win32Printer = new ManagementClass("Win32_Printer");
ManagementObjectCollection printers = win32Printer.GetInstances();
foreach (ManagementObject printer in printers)
{
printer.Delete();
}
}
以示例用户之一或管理员身份在 Windows 8.1 上执行此操作 returns "Access Denied" 使用以下堆栈跟踪:
at System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
at System.Management.ManagementObject.Delete(DeleteOptions options)
at System.Management.ManagementObject.Delete()
at PrintCentralClient.Workstation.unmapPrinter(Printer printerToRemove) in C:\projects\PrintCentralClient\PrintCentralClient\Workstation.cs:line 247
at PrintCentralClient.Program.unmapPrinters(FileLogger log, Workstation workstation) in C:\projects\PrintCentralClient\PrintCentralClient\Program.cs:line 310
at PrintCentralClient.Program.Main(String[] args) in C:\projects\PrintCentralClient\PrintCentralClient\Program.cs:line 75
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
powershell 中的相同想法,获取 Win32_Printer 个实例并对它们进行删除,行得通。
$printers = gwmi Win32_Printer
$printers[i].Delete()
关于为什么我的 C# 代码访问被拒绝有什么想法吗?在代码的其他地方,我成功地使用了 Win32_Printer.AddPrinterConnection() 方法。
谢谢。
编辑 1:
使用 Windows 脚本主机错误 "This network connection does not exist."
演示函数:
public void unmapPrinterViaWSH()
{
IWshNetwork_Class network = new IWshNetwork_Class();
network.RemovePrinterConnection(@"\<server>\<printerName>", true, true);
}
我尝试了一些变体,包括将删除行更改为:
network.RemovePrinterConnection("\\<server>\<printerName>", true, true)
我还尝试枚举打印机连接并使用确切的名称字符串删除:
public void unmapPrinterViaWSH(Printer printerToRemove)
{
IWshNetwork_Class network = new IWshNetwork_Class();
IWshCollection printers = network.EnumPrinterConnections();
foreach (object printer in printers)
{
if (printer.ToString() == printerToRemove.mappedNameToString())
{
network.RemovePrinterConnection(printer.ToString(), true, true);
}
}
}
这失败并出现相同的 "Network connection does not exist" 错误。
对于 WMI:
我缺少 ConnectionsOptions。最初提供的代码示例与它们没有任何关系。在进行早期测试时,我总是先创建范围,然后再创建选项。我发现的另一个参考资料是相反的。这似乎有效。以下是适用于我的代码示例:
public void unmapPrinter()
{
ConnectionOptions options = new ConnectionOptions();
options.EnablePrivileges = true;
ManagementScope scope = new ManagementScope(ManagementPath.DefaultPath, options);
scope.Connect();
ManagementClass win32Printer = new ManagementClass("Win32_Printer");
ManagementObjectCollection printers = win32Printer.GetInstances();
foreach (ManagementObject printer in printers)
{
printer.Delete();
}
}
如果您只想删除特定的打印机,您可以这样做:
using (var printer = new ManagementObject($"Win32_Printer.DeviceID='{printerPath}'"))
printer.Delete();
我的最终目标是取消映射本地工作站上的特定网络打印机。我已经尝试通过 WMI、Windows 脚本宿主和 Winspool.drv Win32 API。我对任何方向的想法都持开放态度。
当使用 WMI 时,我有以下简化的函数,大部分是从 http://www.codeproject.com/Articles/80680/Managing-Printers-Programatically-using-C-and-WMI 复制的:
public void unmapPrinter()
{
ManagementClass win32Printer = new ManagementClass("Win32_Printer");
ManagementObjectCollection printers = win32Printer.GetInstances();
foreach (ManagementObject printer in printers)
{
printer.Delete();
}
}
以示例用户之一或管理员身份在 Windows 8.1 上执行此操作 returns "Access Denied" 使用以下堆栈跟踪:
at System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
at System.Management.ManagementObject.Delete(DeleteOptions options)
at System.Management.ManagementObject.Delete()
at PrintCentralClient.Workstation.unmapPrinter(Printer printerToRemove) in C:\projects\PrintCentralClient\PrintCentralClient\Workstation.cs:line 247
at PrintCentralClient.Program.unmapPrinters(FileLogger log, Workstation workstation) in C:\projects\PrintCentralClient\PrintCentralClient\Program.cs:line 310
at PrintCentralClient.Program.Main(String[] args) in C:\projects\PrintCentralClient\PrintCentralClient\Program.cs:line 75
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
powershell 中的相同想法,获取 Win32_Printer 个实例并对它们进行删除,行得通。
$printers = gwmi Win32_Printer
$printers[i].Delete()
关于为什么我的 C# 代码访问被拒绝有什么想法吗?在代码的其他地方,我成功地使用了 Win32_Printer.AddPrinterConnection() 方法。
谢谢。
编辑 1: 使用 Windows 脚本主机错误 "This network connection does not exist."
演示函数:
public void unmapPrinterViaWSH()
{
IWshNetwork_Class network = new IWshNetwork_Class();
network.RemovePrinterConnection(@"\<server>\<printerName>", true, true);
}
我尝试了一些变体,包括将删除行更改为:
network.RemovePrinterConnection("\\<server>\<printerName>", true, true)
我还尝试枚举打印机连接并使用确切的名称字符串删除:
public void unmapPrinterViaWSH(Printer printerToRemove)
{
IWshNetwork_Class network = new IWshNetwork_Class();
IWshCollection printers = network.EnumPrinterConnections();
foreach (object printer in printers)
{
if (printer.ToString() == printerToRemove.mappedNameToString())
{
network.RemovePrinterConnection(printer.ToString(), true, true);
}
}
}
这失败并出现相同的 "Network connection does not exist" 错误。
对于 WMI:
我缺少 ConnectionsOptions。最初提供的代码示例与它们没有任何关系。在进行早期测试时,我总是先创建范围,然后再创建选项。我发现的另一个参考资料是相反的。这似乎有效。以下是适用于我的代码示例:
public void unmapPrinter()
{
ConnectionOptions options = new ConnectionOptions();
options.EnablePrivileges = true;
ManagementScope scope = new ManagementScope(ManagementPath.DefaultPath, options);
scope.Connect();
ManagementClass win32Printer = new ManagementClass("Win32_Printer");
ManagementObjectCollection printers = win32Printer.GetInstances();
foreach (ManagementObject printer in printers)
{
printer.Delete();
}
}
如果您只想删除特定的打印机,您可以这样做:
using (var printer = new ManagementObject($"Win32_Printer.DeviceID='{printerPath}'"))
printer.Delete();