【发布时间】:2011-04-20 09:11:01
【问题描述】:
我有几个变体来启动屏幕保护程序。我最喜欢的是
[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));
}
我的问题是我想从系统服务中启动屏幕保护程序。如果我例如想在会话锁定后立即启动屏幕保护程序(只是为了证明概念),我可以尝试
protected override void OnSessionChange(SessionChangeDescription changeDescription)
{
base.OnSessionChange(changeDescription);
if (changeDescription.Reason == SessionChangeReason.SessionLock)
startScreensaver();
}
这不起作用,我认为原因是该服务安装了
ServiceProcessInstaller.Account = ServiceAccount.LocalSystem;
它无权访问用户的会话。我可以实现一个在用户会话中运行的小程序,该程序由服务触发以触发屏幕保护程序……但这不是好方法。
有什么建议吗?谢谢。
已编辑:显然问题与GetDesktopWindow(); 通话有关,但我仍然不知道如何解决该问题
更新:
根据 Erics 的建议,我现在迭代所有窗口站(使用 OpenWindowStation),然后对于所有这些我迭代所有桌面(使用 EnumDesktops)。然后我使用 OpenDesktop 打开桌面并将句柄存储到桌面。我的标准 Windows 安装产生以下 windowStation 列表:Desktop:dskHandle
- WinSta0:默认值:732
- WinSta0:断开连接:760
- WinSta0:Winlogon:784
- msswindowstation:mssrestricteddesk:0
我现在开始一个新的线程,我在其中
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetThreadDesktop(IntPtr hDesktop);
然后调用上面的 startScreensaver() 方法。 IntPtr hWnd = GetDesktopWindow() 确实返回了合理的结果,但屏幕保护程序仍未启动。在
[DllImport("user32.dll")]
static extern IntPtr OpenDesktop(string lpszDesktop, uint dwFlags, bool fInherit, uint dwDesiredAccess);
我使用GENERIC_ALL = 0x10000000 作为 dwDesiredAccess。正如 Farzin 所说,我检查了
允许服务与桌面交互
我不是 win32 或 pInvoke 专业人士,所以我现在完全迷失了。某人能解释一下所有的东西是如何一起工作的吗? sb 有更好的建议吗?我要做的就是从系统服务调用屏幕保护程序。
【问题讨论】:
标签: .net windows windows-services screensaver