title: How to start screensaver from system service
body: <p>I have several variants to start the screensaver. I favourite is </p>
  
  <pre><code>[DllImport("user32.dll", SetLastError = false)]
  private static extern IntPtr GetDesktopWindow();
  [DllImport("user32.dll", CharSet = CharSet.Auto)]
  private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
  
  private void startScreensaver()
  {
      UInt32 WM_SYSCOMMAND = 0x112;
      IntPtr SC_SCREENSAVE = new IntPtr(0xf140);
      IntPtr hWnd = GetDesktopWindow();
      SendMessage(hWnd, WM_SYSCOMMAND, SC_SCREENSAVE, new IntPtr(0));
  }
  </code></pre>
  
  <p>My problem is that i want to start the screensaver out of a system service. If i e.g. want to start the screensaver as soon as the session is locked (just for prove of concept), i could try</p>
  
  <pre><code>protected override void OnSessionChange(SessionChangeDescription changeDescription)
  {
      base.OnSessionChange(changeDescription);
      if (changeDescription.Reason == SessionChangeReason.SessionLock)
          startScreensaver();
  }
  </code></pre>
  
  <p>This doesn't work and i think the reason is that the service is installed with the</p>
  
  <p><code>ServiceProcessInstaller.Account = ServiceAccount.LocalSystem;</code></p>
  
  <p>which does not have access to the User's session. I could implement a small program that runs in the user session, which is triggered by the service to trigger the screensaver... but that's not the nice way. </p>
  
  <p>Any suggestions? Thanks.</p>
  
  <p>edited: obviously the problem is related to the <code>GetDesktopWindow();</code> call, still i don't know how to fix that</p>
  
  <p><strong>Update:</strong></p>
  
  <p>According to Erics suggestion, i do now iterate all window station (using OpenWindowStation), then for all of those i iterate all desktops (using EnumDesktops). I then open the desktops using OpenDesktop and store the handle to the desktop. My standard Windows installation yields to the following list of windowStation:Desktop:dskHandle</p>
  
  <ul>
  <li>WinSta0:Default:732</li>
  <li>WinSta0:Disconnect:760</li>
  <li>WinSta0:Winlogon:784</li>
  <li>msswindowstation:mssrestricteddesk:0</li>
  </ul>
  
  <p>I do now start a new Thread in which i </p>
  
  <pre><code>[DllImport("user32.dll", SetLastError = true)]
  static extern bool SetThreadDesktop(IntPtr hDesktop);
  </code></pre>
  
  <p>and then invoke the startScreensaver() method above. The <code>IntPtr hWnd = GetDesktopWindow()</code> does return reasonable results, still the screensaver is not started. In the </p>
  
  <pre><code>[DllImport("user32.dll")]
  static extern IntPtr OpenDesktop(string lpszDesktop, uint dwFlags, bool fInherit, uint dwDesiredAccess);
  </code></pre>
  
  <p>i use <code>GENERIC_ALL = 0x10000000</code> as the dwDesiredAccess. And as Farzin noted, i checked the </p>
  
  <blockquote>
    <p>Allow service to interact with desktop</p>
  </blockquote>
  
  <p>I am not a win32 or pInvoke pro, so i am totally lost now. Can sb explain how all the stuff works together? Does sb has a better suggestion? All I want to do is to invoke the screensaver from a system service.</p>