I'm developing 'Share Monitoring Application' via C# and it's monitoring the sharing activities and I'm using these APIs to implement enumerate shared items/un-sharing shared items.
Api used:
NetShareEnum
NetShareDel
NetShareEnum
to enumerate all shared items and NetShareDel
to delete shared items (=unshare).
I used SHChangeNotify
to remove shared mark and directories working fine.
(Delete shared item using NetShareDel
is not affected immediately.)
But printer state is not affected by SHChangeNotify
. Which mean after deleting shared printer via NetShareDel
and call SHChangeNotify
with SHCNE_NETUNSHARE
and SHCNF_PATHW
. Also I used SHCNE_NETUNSHARE
and SHCNF_PRINTERW
too, but nothing happened.
Shared printer's state mark: https://i.sstatic.net/1ZGrI.png
In this picture, you can see the users the right side of check circle and that indicate printer is shared.
But after calling NetShareDel
to unshared shared printer and it's succeed, but shared mark is disappear.
Anyone know how to implement this? I'm waiting for your help. :D
Sorry for my bad english.
I tried WMI and it works on my computer, but other computers throw an exception. And I think the reason of application throw an exception is the one of required library is missing on the computer. So I'm looking for the API that can be used instead of the WMI.
Finally I found the GetPrinter
and SetPrinter
from the MSDN.
And also I found PRINTER_INFO_5
structure. According to MSDN, Attributes
field indicate the printer's attribute including printer is shared or not. And this can be checked Attributes
field has PRINTER_ATTRIBUTE_SHARED
value.
Anyway, this problem can be solved only OpenPrinter
, GetPrinter
and SetPrinter
.
This image shows the before and after calling 'UnsharePrinter' method.
This is the method I made to un-share the shared printer.
(Un-sharing the shared printer can be performed via NetShareDel
, but it cannot notify printer is un-shared to the system.)
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;
}