Question

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
}
Was it helpful?

Solution

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top