Search code examples
c#screensavershellexecute

Start a screensaver when explorer is not the shell


I'm running my own kiosk application as the shell (replacing HKLM/Software/Microsoft/Windows NT/winlogon/shell).

The application needs to be able to turn off the monitor and I was using Process.Start("scrnsave.scr") to do this. It works on my dev machine but not when the shell is replaced.

It's clearly because the UseShellExecute is set to true, but when I set it to false I can't get the screensaver to run. Using explorer.exe as the command and scrnsave.scr as the argument just causes an explorer window to open.

Is there a switch I can pass to explorer to get it to run the screensaver or is there another way to achieve the same thing?

Thanks.


Solution

  • You can start the screen saver by sending a windows message to the system.

    SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_SCREENSAVE, 0)
    

    You will need the following definitions

    static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff);
    static readonly IntPtr SC_SCREENSAVE = new IntPtr(0xf140);
    const uint WM_SYSCOMMAND = 0x112;
    
    [DllImport("User32",SetLastError=true)]
    extern static int SendMessage(
      IntPtr hWnd,
      uint Msg,
      IntPtr wParam,
      IntPtr lParam);
    

    Which you can then use as follows

    SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_SCREENSAVE, IntPtr.Zero);