从服务中以交互方式启动.Net winforms应用程序

时间:2009-02-19 11:14:18

标签: c++ winforms winapi windows-services

环境 - VS2008,Vista SP1。

我编写了一个流程管理服务,可以在会话0或交互式控制台(通常为1)中启动应用程序。请注意,这不是正常的操作模式,仅用于内部调试。在现场,这些过程将在会话0中安全地隐藏起来。安全问题不适用。

显然,人们不会读到这一点:安全问题不适用。我们有几十个这样编写的现有服务器应用程序(非服务)。我们不打算彻底改进这些应用程序,我们只需要在内部运行发布版本时就可以使用内置的调试对话框。我已经了解了有关规范解决方案和管道等的所有信息。如果可以将远程接口添加到所有这些应用程序中,那就是我们要做的事情。

我使用以下代码执行此操作:

ZeroMemory (&sui, sizeof(STARTUPINFO));
sui.cb = sizeof (STARTUPINFO);
sui.wShowWindow = pTask->GetWinStartState() ;
sui.dwFlags     = STARTF_USESHOWWINDOW ;
ZeroMemory (&pi,sizeof(pi));

if (bInteractive)
{
   HANDLE  hToken = NULL;
   DWORD dwSessionId = WTSGetActiveConsoleSessionId();
   WTSQueryUserToken (dwSessionId, &hToken);
   sui.lpDesktop = TEXT("winsta0\\default"); 
   LPVOID  pEnv = NULL;
   DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
   HMODULE hModu = LoadLibrary(TEXT("Userenv.dll"));

   if (hModu )
   {
      if (CreateEnvironmentBlock (&pEnv, hToken, FALSE))
         dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;    
      else
         pEnv = NULL;
   }

   bCreatedOk = CreateProcessAsUser (hToken,
                                     NULL,
                                     (LPTSTR)(pTask->GetExeName()),
                                     NULL,
                                     NULL,
                                     FALSE,
                                     dwCreationFlag,
                                     pEnv,
                                     NULL,
                                     &sui,
                                     &pi);
}
else
{
   bCreatedOk = CreateProcess (NULL, ... blah...);
}

这一切都运行良好,我可以在Vista服务会话和控制台中运行和监视本机进程。大。每个人都有蛋糕和啤酒。

所以这就是问题所在。如果我尝试以交互方式运行 winforms (C#)应用程序,它似乎运行,在Process Explorer中显示为在会话1中运行,但在桌面上... nada。根本没有窗口出现。该过程运行起来并关闭所有罚款,但没有窗口出现。从资源管理器运行的完全相同的winform exe也出现在会话1中,但这次出现在桌面上就好了。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

尽管存在明显的歇斯底里,但如果使用与交互式用户相同的权限或更低的,则将应用程序从服务启动到交互式会话中没有任何问题。由于您作为交互式用户启动,因此无法进行权限提升。

你在做什么工作。我怀疑这个问题与你的STARTUPINFO结构有关。你似乎是在堆栈上创建你的sui,但你没有显示你正在做什么。你是不是把它初始化为全0,如果没有,你可能会从堆栈中得到一些垃圾,导致窗口无法显示或显示在屏幕的某些坐标上。

答案 1 :(得分:0)

总之,“不要”。

服务通常以降低的权限运行,而不是以当前用户身份运行。因此,在Vista +中,他们不允许与用户桌面进行交互。最重要的是,服务获得一个空的Window Station。

您曾经能够检查一个类似“允许与桌面交互”的框,但现在不行了。这是不好的做法。

最好的办法是创建一个在用户上下文中运行的帮助应用程序,并通过命名管道,LRPC或套接字与服务进行通信,然后让您的帮助应用程序为用户启动该程序。这是大多数反病毒现在的工作方式。

另外,请阅读Microsoft关于此主题的this whitepaper。除了会话0以外,服务不能运行。

注意:一点研究似乎表明您需要使用以下内容复制令牌:

DuplicateTokenEx(hTokenNew,MAXIMUM_ALLOWED,NULL,
    SecurityIdentification,TokenPrimary,&hTokenDup);

答案 2 :(得分:0)

看起来你正试图打破会话隔离。就像Mystere Man所说,我认为这不是正确的事。

如果您真的想要这样做,

http://support.microsoft.com/?scid=kb%3Ben-us%3B165194&x=5&y=3可能会有用。在那里的代码示例中,他们似乎初始化了比你更多的东西。


编辑如果是出于调试目的,i-e VS 2008单步执行,只需在开头添加一个等待循环,然后以管理员权限启动VS.您可以在不遇到系统隔离的情况下附加到服务进程。