如何获取当前登录用户的会话ID?

时间:2010-07-07 17:07:57

标签: c# process service psexec createprocessasuser

我正在使用

从Windows服务中运行一个进程
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

万岁,现在有效! 但!现在我需要将程序带到当前登录用户的屏幕。要做到这一点,我需要会话ID!

所以问题是:如何获取当前登录用户的会话ID?如果还没有人登录会怎么样?会话ID是什么?

UPD4:就是这样!我有那个!

[DllImport(“Kernel32.dll”,EntryPoint =“WTSGetActiveConsoleSessionId”)]  public static extern int WTSGetActiveConsoleSessionId();

谢谢你们!

4 个答案:

答案 0 :(得分:3)

一种解决方案是让第三个进程充当中介,并告诉它通过RPC /命名管道启动应用程序。

过程:

  • Windows服务
  • 中介申请
  • 您要投放的应用

shim创建一个通信端点(命名管道,WCF端点)并监听它。当它收到要继续的消息时,它会启动您要运行的应用程序。

然后,当Windows服务想要启动应用程序时,它会找到并打开端点(命名管道,WCF端点),并发送消息以启动应用程序。然后,中间应用程序负责流程启动业务,并且没有Windows服务的任何限制。

让这个中间过程从登录开始,你很高兴。

这类似于Microsoft测试代理/控制器在您需要运行与桌面交互的测试时的工作方式。

答案 1 :(得分:3)

您可以使用WTSGetActiveConsoleSessionId(来自终端服务API)获取活动控制台会话ID。您只能将它用于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或更高版本的机器上运行。

答案 2 :(得分:2)

这可以在没有中间过程的情况下完成,但它需要超过500行代码。基本上,您希望以当前登录用户的身份启动第二个进程。对于Vista / 7,此用户将拥有自己的winlogon进程,而对于XP,他们将拥有一个资源管理器进程。您需要获取正在运行的进程的主令牌,环境块,安全属性和线程安全属性,然后使用所有信息调用Windows API函数CreateProcessAsUser,确保您也选择正确的窗口站(通常为“WinSta0 \ Default” “)。这一切都是可行的,但您可能会有更好的时间来处理第二个流程和IPC的其他建议。

答案 3 :(得分:1)

如果你在比WindowsXP更新的任何东西上尝试这个,这将无效。这是因为Vista / Windows 7中引入了一项称为Session 0隔离的新功能。 http://msdn.microsoft.com/en-us/library/bb756986.aspx您将无法通过服务启动应用以显示在用户桌面上。