长话短说,我正在尝试向作为Windows服务运行的自定义更新程序添加一些功能。我遇到了一些问题,试图更新的应用程序可能正在运行,如果需要,我需要执行一些自定义操作。
我遇到的问题是EnumDesktopWindows api调用仅返回在本地系统上下文中运行的进程。
现在,这对于我为什么这样做是最有意义的(依此类推(我想-尽管会进一步解释))。
但是,如何通过一项服务来实现这一功能呢?
这是我正在使用的代码的基础:
public static IntPtr[] EnumDesktopWindows()
{
WinAPI._desktopWindowHandles = new List<IntPtr>();
WinAPI.EnumDelegate enumfunc = new WinAPI.EnumDelegate(EnumWindowsCallBack);
IntPtr hDesktop = IntPtr.Zero; // current desktop
bool success = WinAPI.EnumDesktopWindows(hDesktop, enumfunc, IntPtr.Zero);
if (success)
{
IntPtr[] handles = new IntPtr[_desktopWindowHandles.Count];
_desktopWindowHandles.CopyTo(handles);
return handles;
}
else
{
int errorCode = Marshal.GetLastWin32Error();
string errorMessage = String.Format("EnumDesktopWindows failed with code {0}.", errorCode);
throw new Exception(errorMessage);
}
}
可能是我全都错了,问题就在这里吗?:
IntPtr hDesktop = IntPtr.Zero;
最佳答案
我不确定您列举的台式机方向是否正确。我不知道谁是服务内部EnumDesktopWindows调用之后的操作的发起者。如果用户触发了该操作,那么您可能可以模拟他的用户帐户,并且该问题将很容易解决。
如果您无法接收用户令牌,我建议您先阅读Impact of Session 0 Isolation on Services and Drivers in Windows文档,然后再继续。您遇到的主要问题是终端服务正在计算机上运行,而Windows服务在会话ID为0的会话中运行,但是所有用户进程在另一个会话中运行。如果您的服务在LocalSystem
帐户下或在具有SE_TCB_NAME
特权的任何其他帐户下运行,则可以将SetTokenInformation函数与TokenSessionId
参数一起使用以更改为当前会话(有关更多详细信息,请参见here)。关于LsaEnumerateLogonSessions功能,您可以收到的所有可用会话。
最后,我可以再重复一遍,只有在无法使用其他更简单的方式(例如用户模拟)时,才应该更改服务会话。
关于c# - Windows Service中的EnumDesktopWindows,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5298351/