如何取消共享共享打印机?

时间:2015-05-18 00:44:02

标签: c# windows printing share shared

我正在开发共享监控应用程序'通过C#和它监控共享活动,我使用这些API实现枚举共享项目/取消共享共享项目。

使用Api:

NetShareEnum
NetShareDel


NetShareEnum枚举所有共享项目,NetShareDel删除共享项目(=取消共享) 我使用SHChangeNotify删除共享标记和目录正常工作。
(使用NetShareDel删除共享项目不会立即受到影响。)

但是打印机状态不受SHChangeNotify的影响。这意味着在通过NetShareDel删除共享打印机并使用SHChangeNotifySHCNE_NETUNSHARE致电SHCNF_PATHW后。我也使用了SHCNE_NETUNSHARESHCNF_PRINTERW,但没有发生任何事情。

共享打印机的状态标记: http://i.stack.imgur.com/1ZGrI.png
在此图片中,您可以看到用户在检查圈的右侧并指示打印机已共享 但是在将NetShareDel称为非共享共享打印机并且它成功后,但共享标记消失了。

任何人都知道如何实现这个?我在等你的帮助。 :d
抱歉我的英语不好。

2 个答案:

答案 0 :(得分:1)

您是否尝试过通过WMI? 我自己还没有用它来#tre; unshare"打印机,但我在应用程序中使用它很多以其他方式编辑打印机和打印机端口。 我认为这样的事情可以解决问题。

Win32_Printer类看起来像是"共享"属性,所以我建议尝试将其切换为false。 https://msdn.microsoft.com/en-us/library/aa394363%28v=vs.85%29.aspx

我还没有通过取消共享测试此代码,但它与我用来更改其他属性的代码完全相同。

//get the printer(s) through wmi query
//prep query
SelectQuery query = new SelectQuery(string.Format("select * from Win32_Printer WHERE Name = '{0}'", "printername"));
//create scope (connect to server)
ManagementScope scope = new ManagementScope("\\\\serverName\\root\\cimv2");
//search for printers
ManagementObjectSearcher search = new ManagementObjectSearcher(scope, query);
//get collection of printers (should be 0 or 1, but it returns a collection regardless because of the query
ManagementObjectCollection printers = search.Get();
//iterate through the 0-1 printers and set Shared to false
foreach (ManagementObject printer in printers)
{
    printer.SetPropertyValue("Shared",false);
    printer.put();
}

答案 1 :(得分:1)

我尝试了WMI,它可以在我的计算机上运行,​​但其他计算机会抛出异常。我认为应用程序抛出异常的原因是计算机上缺少必需的库。 所以我正在寻找可以用来代替WMI的API。

最后,我从MSDN找到了GetPrinterSetPrinter

我也发现了PRINTER_INFO_5结构。根据MSDN,Attributes字段表示打印机的属性包括打印机是否共享。可以检查此Attributes字段的值为PRINTER_ATTRIBUTE_SHARED

无论如何,只有OpenPrinterGetPrinterSetPrinter才能解决此问题。



此图显示调用'UnsharePrinter'方法之前和之后。 Before and After the calling UnsharePrinter method

这是我取消共享共享打印机的方法 (可以通过NetShareDel取消共享共享打印机,但无法将打印机取消共享通知系统。)

Boolean UnsharePrinter(String printerName) {
    // fill PRINTER_DEFAULTS structure
    // and set DesiredAccess to PRINTER_ACCESS_ADMINISTER to 
    // get rights to call SetPrinter
    PRINTER_DEFAULTS pd;
    pd.pDatatype = IntPtr.Zero;
    pd.pDevMode = IntPtr.Zero;
    pd.DesiredAccess = PRINTER_ACCESS_ADMINISTER;

    IntPtr pDefaults = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PRINTER_DEFAULTS)));
    Marshal.StructureToPtr(pd, pDefaults, true);

    IntPtr hPrinter;
    // open the printer
    if ( !OpenPrinter(printerName, out hPrinter, pDefaults) ) {
        Marshal.FreeHGlobal(pDefaults);
        return false;
    }

    // first, call Zero pointer and 0 size to get minimum required space
    IntPtr pInfo = IntPtr.Zero;
    Int32 pcbNeeded;
    GetPrinter(hPrinter, 5, pInfo, 0, out pcbNeeded);

    // alloc reqiured space and call GetPrinter
    pInfo = Marshal.AllocHGlobal(pcbNeeded);
    if ( !GetPrinter(hPrinter, 5, pInfo, pcbNeeded, out pcbNeeded) ) {
        Marshal.FreeHGlobal(pInfo);
        ClosePrinter(hPrinter);
        return false;
    }

    // pointer to structure
    PRINTER_INFO_5 pi5 = (PRINTER_INFO_5) Marshal.PtrToStructure(pInfo, typeof(PRINTER_INFO_5));
    Marshal.FreeHGlobal(pInfo);

    // if printer is not shared, release the memory and exit
    if ( (pi5.Attributes & PRINTER_ATTRIBUTE_SHARED) == 0 ) {
        ClosePrinter(hPrinter);
        return false;
    }

    // remove the shared flag
    pi5.Attributes &= ~PRINTER_ATTRIBUTE_SHARED;

    // alloc pointer and make structure as pointer
    pInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PRINTER_INFO_5)));
    Marshal.StructureToPtr(pi5, pInfo, true);

    // set printer
    Boolean r = SetPrinter(hPrinter, 5, pInfo, 0);
    Marshal.FreeHGlobal(pInfo);
    ClosePrinter(hPrinter);

    return r;
}