如何获取当前记录的用户会话ID?
我从Windows服务中使用如何获取当前记录的用户会话ID?
ProcessStartInfo processStartInfo = new ....
Process.Start(processStartInfo);
的问题是运行过程中,如果我在本地系统帐户下运行的服务,它运行正常的,但它并不显示程序窗口。 我试图把用户凭据放在服务属性中,但'允许服务与桌面交互'复选框变为禁用状态。
我真的需要运行应用程序从服务调用它,我真的需要看到应用程序的窗口。
请帮助我。
UPD。那么,你使用过载的版本的Process.Start需要用户名,密码和域 - 它会将程序拖到桌面上。但现在它启动应用程序在一个凭据下,但显示在不同的用户的桌面上。怎么来的?
UPD2:我有个主意!我可以使用Sysinternals Suite中的psexec.exe。但问题是我需要以“管理员”的身份默默地开始这件事。我不知道如何。 我的意思是,即使你已经拥有管理员权限,有时你也必须手动说出“以管理员身份运行”,确认UAC并且只有在你准备好后才能进行。我不知道如何静静地运行一些东西,但不带UAC的东西......
UPD3:亲爱的主。我有这个东西!最后。
好的。在开始时,问题确实在会话0隔离的事情。所以我需要构建一个可以从服务启动的中间应用程序,然后,该应用程序又将通过RPC启动我的应用程序并将其引入桌面。与其构建中间层应用程序,我决定使用psexec工具(无论如何,它的工作方式与我需要的完全相同 - 通过RPC)。 当我尝试在LOCAL SYSTEM帐户下使用该工具时,由于某种原因它不起作用。然后我意识到 - 原因是MS放在每一个pstool中的该死的EULA弹出对话框,并且不可能在本地系统帐户下点击按钮确认对话框。 所以解决的办法是在注册表HKU.DEFAULT \ Software \ Sysinternals \ PsExec中用DWORD值创建一个密钥EulaAccepted = 1
Hooray,现在工作! 但是!现在我需要将程序带到当前记录的用户屏幕。要做到这一点,我需要会话ID!
所以问题是:如何获取当前登录的用户的会话ID?如果没有人登录,会发生什么?会是什么会话ID?
UPD4:就是这样!我有那个! (DllImport(“Kernel32.dll”,EntryPoint =“WTSGetActiveConsoleSessionId”)] public static extern int WTSGetActiveConsoleSessionId();
谢谢你们!
一种解决方案是让第三个进程充当中介,并通过RPC /命名管道启动应用程序。
过程:
- Windows服务
- 中介申请
- 要运行
垫片的应用程序创建一个通信端点(命名管道,WCF端点)和侦听它。当它收到一条消息时,它会启动你想运行的应用程序。
然后,当Windows服务想要启动应用程序时,它会查找并打开端点(命名管道,WCF端点),并发送消息以启动应用程序。然后,中介应用程序负责流程启动业务,并且不具有Windows服务具有的任何限制。
使这个中间过程开始登录,你很好去。
这与Microsoft测试代理/控制器在需要运行与桌面交互的测试时的工作方式类似。
Ahhhh ...有没有更简单的解决方案? 我试图从SysInternals套件中启动一个psexec.exe应用程序。您可以将会话ID提供给它,它会将该应用程序带到使用该会话的该用户的桌面。 但问题是,它需要以管理员身份启动。 例如,如果你甚至试图运行这样的东西: PsExec.exe -u mydomain \ user -p pass123 -i -s 1“c:\ windows \ system32 \ calc.exe” 即使用户具有管理员权限,该脚本将工作,除非你手动说“以管理员身份运行”。我如何以管理员的身份悄悄地运行某些东西而不带UAC的东西? – Agzam 2010-07-08 13:17:56
如果您尝试使用比WindowsXP更新的任何东西,这将无法正常工作。这是因为在Vista/Windows 7中引入了一个称为会话0隔离的新功能。 http://msdn.microsoft.com/en-us/library/bb756986.aspx您将无法获得由服务启动的应用程序以显示在用户桌面上。
这可以在没有中间过程的情况下完成,但它需要500多行代码才能完成。基本上,您想要以当前登录用户的身份启动第二个进程。对于Vista/7,此用户将拥有自己的winlogon进程,而对于XP,他们将拥有一个浏览器进程。您需要获取该运行过程的主令牌,环境块,安全属性和线程安全属性,然后使用所有信息调用Windows API函数CreateProcessAsUser,并确保选择了正确的窗口工作站(通常为“WinSta0 \ Default “)。这一切都是可行的,但是对于第二个过程和IPC的其他建议,您可能会有更好的时间。
我试过了,还是不带窗口。该死的0隔离东西... – Agzam 2010-07-08 17:29:57
您可以使用WTSGetActiveConsoleSessionId(来自终端服务API)获取活动控制台会话标识。你只能在WinXP/Win2K3或更高版本上使用它,但这应该没问题,因为你可以在Win2K或更早版本上为会话ID硬编码0。下面是它的PInvoke签名:
[DllImport("Kernel32.dll", SetLastError = true)]
[return:MarshalAs(UnmanagedType.U4)]
public static extern int WTSGetActiveConsoleSessionId ();
至于在用户的会话启动一个过程,你可以参考我给here答案。它基本上涉及调用四个API; WTSGEtConsoleSessionId,WTSQueryUserToken,DuplicateTokenEx,然后是CreateProcessAsUser,它可以在任何运行WinXP/Win2K3或更高版本的机器上运行。
-1:这个答案已经在问题中。 – 2010-09-04 07:04:08
对不起,我意识到我误解了实际问题并更新了我的帖子以提供更好的答案。 – Javert93 2010-09-04 07:18:44
我重新阅读我的答案,并意识到我只给了你一半的解决方案......你应该拼凑你的最终解决方案,并将其添加为答案而不是问题。在这里发表回答你自己的问题是可以的:)让未来有人阅读这篇文章更清楚(有人会 - 这是一个比较常见的问题)。 – 2011-10-02 19:22:11