问题
I am looking for a way to detect when the default printer was changed on an RDP session. Basically we are trying to record the users last default printer and I feel the easiest way to perform this task is to detect when the user changed printers as opposed to capturing the default when they log off. I have looked at several options so far, some of them are below.
Solution 1
Attempt to attach to the local print monitor to check for the change of default printer. I found this URL FindPrinterFirstChangeNotification. Which I thought would work by filtering with the PRINTER_CHANGE_SET_PRINTER
flag. However, I received no events when I changed the default printer in the UI.
Solution 2
The next option was to potentially create a new driver with the WDK to catch when the printer changed defaults.
Does anyone else have any ideas on capturing this event? I don't know if there is any other methodology to making it happen.
Below is the code I used for the FindFirstPrinterChangeNotification
. I was able to capture events on the print jobs themselves but I wasn't able to capture anything in regards to the changing of the default printer.
IntPtr test = IntPtr.Zero;
PRINTER_DEFAULTS defaults = new PRINTER_DEFAULTS { DesiredAccess = PrinterAccessRights.READ_CONTROL };
Printer.OpenPrinter("Microsoft XPS Document Writer", out test, ref defaults);
Operations.Log(new Win32Exception(Marshal.GetLastWin32Error()).Message, System.Diagnostics.EventLogEntryType.Error, 4);
Printer.FindChangedEvent(test);
Method for capturing event.
public static void FindChangedEvent(IntPtr handle) {
IntPtr ptr = FindFirstPrinterChangeNotification(handle, (uint)Printer_Change.ALL, 0, null);
Operations.Log(new Win32Exception(Marshal.GetLastWin32Error()).Message, System.Diagnostics.EventLogEntryType.Error, 4);
ManualResetEvent _ManualResetEvent = new ManualResetEvent(false);
_ManualResetEvent.SafeWaitHandle = new SafeWaitHandle(ptr, true);
RegisteredWaitHandle _RegisteredWaitHandle = ThreadPool.RegisterWaitForSingleObject(_ManualResetEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), null, -1, true);
}
Event method
private static void PrinterNotifyWaitCallback(object state, bool timedOut) {
if (timedOut) {
//Should not happen
return;
} else {
}
}
Struct for flags
[Flags]
public enum Printer_Change : uint {
ADD_PRINTER = 0x00000001,
SET_PRINTER = 0x00000002,
DELETE_PRINTER = 0x00000004,
FAILED_CONNECTION_PRINTER = 0x00000008,
PRINTER = 0x000000FF,
ADD_JOB = 0x00000100,
SET_JOB = 0x00000200,
DELETE_JOB = 0x00000400,
WRITE_JOB = 0x00000800,
JOB = 0x0000FF00,
ADD_FORM = 0x00010000,
SET_FORM = 0x00020000,
DELETE_FORM = 0x00040000,
FORM = 0x00070000,
ADD_PORT = 0x00100000,
CONFIGURE_PORT = 0x00200000,
DELETE_PORT = 0x00400000,
PORT = 0x00700000,
ADD_PRINT_PROCESSOR = 0x01000000,
DELETE_PRINT_PROCESSOR = 0x04000000,
PRINT_PROCESSOR = 0x07000000,
ADD_PRINTER_DRIVER = 0x10000000,
SET_PRINTER_DRIVER = 0x20000000,
DELETE_PRINTER_DRIVER = 0x40000000,
PRINTER_DRIVER = 0x70000000,
TIMEOUT = 0x80000000,
ALL = 0x7777FFFF
}
回答1:
The PRINTER_CHANGE_SET_PRINTER
flag is only going to fire an event when a printer itself is changed. Setting a default print doesn't change that printer object.
If you wanted notification of the change of default printer, use a registry watcher to monitor the Device
value under the HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows
key.
Either implement RegNotifyChangeKeyValue or use something like this: http://www.codeproject.com/Articles/4502/RegistryMonitor-a-NET-wrapper-class-for-RegNotifyC
来源:https://stackoverflow.com/questions/20529075/how-do-i-tell-when-the-default-printer-was-changed