如何在c#中删除网络打印机连接

时间:2016-05-25 20:07:48

标签: c# printing wmi network-printers

我的最终目标是取消映射本地工作站上的特定网络打印机。我尝试过WMI,Windows Script Host和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上作为示例用户之一或作为管理员执行此操作将返回" 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 Scripting Host错误输出"此网络连接不存在。"

演示功能:

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

此失败并且#34;网络连接不存在&#34;错误。

2 个答案:

答案 0 :(得分:1)

对于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();
    }
}

答案 1 :(得分:0)

如果您只想删除特定的打印机,则可以执行以下操作:

using (var printer = new ManagementObject($"Win32_Printer.DeviceID='{printerPath}'"))
    printer.Delete();