我有几个变种来启动屏幕保护程序。我最喜欢的是
[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列表:桌面:dskHandle
我现在开始一个新的线程,其中我
[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专业版,所以我现在完全迷失了。可以解释一下这些东西是如何协同工作的吗?某人有更好的建议吗?我想做的就是从系统服务中调用屏幕保护程序。
答案 0 :(得分:2)
答案 1 :(得分:1)
转到您的服务,右键单击服务,然后在LogOn选项卡中将项目设置为true:
允许服务与桌面交互
如果您想在安装时执行此操作:
public WindowsServiceInstaller()
{
// This call is required by the Designer.
InitializeComponent();
ServiceInstaller si = new ServiceInstaller();
si.ServiceName = "WindowsService1";
si.DisplayName = "WindowsService1";
si.StartType = ServiceStartMode.Manual;
this.Installers.Add(si);
ServiceProcessInstaller spi = new ServiceProcessInstaller();
spi.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
spi.Password = null;
spi.Username = null;
this.Installers.Add(spi);
// Here is where we set the bit on the value in the registry.
// Grab the subkey to our service
RegistryKey ckey = Registry.LocalMachine.OpenSubKey(
@"SYSTEM\CurrentControlSet\Services\WindowsService1", true);
// Good to always do error checking!
if(ckey != null)
{
// Ok now lets make sure the "Type" value is there,
//and then do our bitwise operation on it.
if(ckey.GetValue("Type") != null)
{
ckey.SetValue("Type", ((int)ckey.GetValue("Type") | 256));
}
}
}
参考:http://www.codeproject.com/KB/install/cswindowsservicedesktop.aspx
答案 2 :(得分:1)
安装时允许服务与桌面交互可能会有效(将SERVICE_INTERACTIVE_PROCESS
传递给CreateService
)。否则(可能存在访问问题 - 我没有尝试过)你需要从Window Station and Desktop Functions开始。
您需要做的是找到登录用户窗口站(EnumWindowStations
,OpenWindowStation
),桌面(EnumDesktops
,OpenDesktop
),创建一个主题和SetThreadDesktop
,然后最后使用GetDesktopWindow
。