从Windows服务加载GUI应用程序

我正在编写.NET Windows服务,其作用是启动GUI应用程序(其源不可用)。 除了初始命令行参数之外,操作是一场火灾,忘记了,没有任何交stream。

该服务应该作为给定的Windows帐户运行。

问题:服务启动的应用程序显示在桌面上。 它需要,因为它是一个交互式的应用程序。 解决办法是什么?

注意:这是系统的规格和devise。 服务/应用程序通信和安全方面提出的典型问题不适用于此特定情况。

编辑:当以本地系统帐户login时,GUI元素显示正确,但由于GUI应用程序需要访问联网驱动器(无法理解UNC映射),因此需要将其作为指定的用户帐户运行,没有“显示交互元素”设置。

编辑2:操作系统是Windows 2003 Server,并没有计划升级它。

不幸的是,自从Vista以来,这个问题就变得更加严重了。关于为什么发布在这篇博文上的一些细节。

这篇文章提到了一些潜在的解决方法。 这里是MSDN上的一个线程 ,详细介绍了整个过程,以及一些潜在的打嗝问题。

不过,我强烈建议您尝试查看是否可以切换到将用户模式应用程序作为启动应用程序(用户登录时)运行,并且任何与您的服务的通信都由该应用程序处理。 这是更可靠的,特别是在Vista,终端服务和其他情况下。

这是在黑暗中刺,但希望会导致你的解决方案的某种途径。

即使安全不是问题,也可能是问题。 该服务将在与当前登录的用户不同的凭据集下启动应用程序。 这将像远程桌面到用户机器,并启动他们将看到的应用程序。

作为一个测试,也许可以将服务的凭据更改为当前登录的用户,以查看会发生什么。

由于即使用户没有登录,服务也能运行,如果启动应用程序会发生什么? 您的业​​务规则或功能可能会阻止这种情况的发生,但也许Windows正在做一些工作。

您可以从Sysinternals / Microsoft使用免费的Autologon实用程序http://technet.microsoft.com/en-us/sysinternals/bb963905.aspx ,并将您的应用程序放入启动自动登录用户配置文件。 之后,您可以配置屏幕服务器在几分钟内启动,然后选中“恢复,显示登录屏幕”复选框。

当您启用终端服务器角色时,您是否期望您的应用程序/服务能够工作? 如果是这样,你真的需要做“轮询服务的应用程序”模型,而不是“启动应用程序的服务”模型。

原因是您可能有多个用户随时连接到本机,无法知道哪个是在“控制台” – 事实上在控制台上可能没有人。

这是我以前在任务管理服务中使用的代码,它有时需要在交互式会话中运行。 用您的应用程序替换wibble.exe。 它应该运行良好的server 2003(即NT5)。 我们没有试图在NT6上运行交互模式(太麻烦了),我们离开了我们的应用程序运行在服务会话,并编写我们自己的调试工具,通过管道与他们交谈。

STARTUPINFO sui ; PROCESS_INFORMATION pi; ZeroMemory (&sui, sizeof(STARTUPINFO)); sui.cb = sizeof (STARTUPINFO); sui.wShowWindow = pTask->GetWinStartState(); sui.dwFlags = STARTF_USESHOWWINDOW; ZeroMemory (&pi,sizeof(pi)); if (InteractiveMode) { HANDLE hToken = NULL; DWORD dwSessionId = GetCurrentUserSession(); if (dwSessionId != (DWORD)-1) { if (WTSQueryUserToken (dwSessionId, &hToken)) { sui.lpDesktop = TEXT("winsta0\\default"); LPVOID pEnv = NULL; dwCreateFlags |= CREATE_NEW_CONSOLE; HMODULE hModu = LoadLibrary(TEXT("Userenv.dll")); if (hModu) { if (CreateEnvironmentBlock (&pEnv, hToken, FALSE)) { dwCreateFlags |= CREATE_UNICODE_ENVIRONMENT; } else { pEnv = NULL; } } bCreatedOk = CreateProcessAsUser (hToken, NULL, TEXT("wibble.exe"), NULL, NULL, FALSE, dwCreateFlags, pEnv, NULL, &sui, &pi); } else { // error case } } else { // remote session? error case. } } 

我在想,你的“指定的用户帐户”必须是这里的控制台会话。 如果你需要它运行在一个指定的帐户没有该帐户已经登录,你是在一个全新的世界受到伤害,加载注册表配置单元等