I have several variants to start the screensaver. I favourite is
[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));
}
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
protected override void OnSessionChange(SessionChangeDescription changeDescription)
{
base.OnSessionChange(changeDescription);
if (changeDescription.Reason == SessionChangeReason.SessionLock)
startScreensaver();
}
This doesn't work and i think the reason is that the service is installed with the
ServiceProcessInstaller.Account = ServiceAccount.LocalSystem;
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.
Any suggestions? Thanks.
edited: obviously the problem is related to the GetDesktopWindow(); call, still i don't know how to fix that
Update:
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
- WinSta0:Default:732
- WinSta0:Disconnect:760
- WinSta0:Winlogon:784
- msswindowstation:mssrestricteddesk:0
I do now start a new Thread in which i
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetThreadDesktop(IntPtr hDesktop);
and then invoke the startScreensaver() method above. The IntPtr hWnd = GetDesktopWindow() does return reasonable results, still the screensaver is not started. In the
[DllImport("user32.dll")]
static extern IntPtr OpenDesktop(string lpszDesktop, uint dwFlags, bool fInherit, uint dwDesiredAccess);
i use GENERIC_ALL = 0x10000000 as the dwDesiredAccess. And as Farzin noted, i checked the
Allow service to interact with desktop
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.