2010-07-28 69 views
5

我有一个windows系统,它在系统帐户下运行并且不时执行一些程序(是的,是的,我知道这是一种不好的做法,但那不是我的决定)。我需要设置“与桌面交互”检查,以便在安装服务之后查看执行的程序的GUI。我尝试了几种方法,把下面的代码在AfterInstall或OnCommited我的服务安装程序的事件处理程序:如何在windows服务安装程序中设置“与桌面交互”

ConnectionOptions coOptions = new ConnectionOptions(); 
coOptions.Impersonation = ImpersonationLevel.Impersonate; 

ManagementScope mgmtScope = new System.Management.ManagementScope(@"root\CIMV2", coOptions); 
mgmtScope.Connect(); 

ManagementObject wmiService = new ManagementObject("Win32_Service.Name='" + ServiceMonitorInstaller.ServiceName + "'"); 

ManagementBaseObject InParam = wmiService.GetMethodParameters("Change"); 
InParam["DesktopInteract"] = true; 
ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null); 

RegistryKey ckey = Registry.LocalMachine.OpenSubKey(
    @"SYSTEM\CurrentControlSet\Services\WindowsService1", true); 

    if(ckey != null) 
    { 
    if(ckey.GetValue("Type") != null) 
    { 
     ckey.SetValue("Type", ((int)ckey.GetValue("Type") | 256)); 
    } 
    } 

这两种方法的“工作”。他们设置了支票,但是在我启动服务后,它启动了exe文件 - 并且gui没有显示!所以,如果我停止服务,重新检查并重新启动它 - 宾果!一切都开始并显示。实现结果的第二种方法是重新启动 - 之后显示gui。

所以问题是:有没有一个正确的方法来设置“与桌面交互”检查,所以它会开始工作,无需复查和重新启动?

操作系统:Windows XP(没有尝试过Vista和Windows 7尚未...)

+0

试图使用“sc config”命令 - 没有办法... – 2010-07-28 11:45:44

+0

试图使用winapi从http://www.codeproject.com/KB/vb/WindowsServiceInstall.aspx导出 - 没有运气... – 2010-07-28 13:05:41

回答

2

最后寻找了一个星期后上网 - 我已经找到了理想的工作方案: http://asprosys.blogspot.com/2009/03/allow-service-to-interact-with-desktop.html

找到要启动的桌面。这个 可能看起来很滑稽,但它并不像 那样简单。用终端 服务和快速用户切换那里 可以是多个交互式用户 登录到计算机在相同的 时间。如果您希望 当前坐在物理 控制台上的用户,那么您很幸运, 终端服务API调用 WTSGetActiveConsoleSessionId将获得您需要的会话ID 。如果您 需求更复杂(即需要 与一个 TS服务器上的特定用户进行交互,或者您需要在非交互式 会议 窗口站的名称),你需要枚举 终端与 WTSEnumerateSessions进行服务器会话并检查 会话以了解您需要的信息 与WTSGetSessionInformation。

现在你知道你需要什么会话 与之交互,你有它的ID。 这是整个过程的关键, 使用WTSQueryUserToken和 会话ID您现在可以检索登录到 目标会话的用户的标记 。这完全 减轻了 的安全问题“与桌面交互”设置, 启动的过程不会是 与本地系统运行 凭据,但具有相同 凭据,因为这是 用户已经登录到该会!没有 特权提升。

使用CreateProcessAsUser,我们已经获取的,我们可以以正常的方式启动 过程中 令牌,并将其 将在目标会话中运行与 目标用户的凭据。有 有几个需要注意的地方,无论是 lpCurrentDirectory和lpEnvironment 必须指向有效的价值 - 为 的 正常的默认分辨率方法这些参数不为 跨会话启动工作。您可以使用 CreateEnvironmentBlock为 目标用户创建 默认环境块。

附有工作项目的源代码。

+0

This Code是伟大的,但没有人知道如何在启动应用程序时指定参数? – 2011-02-22 22:22:54

4
private static void SetInterActWithDeskTop() 
     { 
      var service = new System.Management.ManagementObject(
        String.Format("WIN32_Service.Name='{0}'", "YourServiceName")); 
      try 
      { 
       var paramList = new object[11]; 
       paramList[5] = true; 
       service.InvokeMethod("Change", paramList); 
      } 
      finally 
      { 
       service.Dispose(); 
      } 


     } 
+0

此方法有效。它正确设置标志。 – 2012-06-23 21:04:15

+0

工程很好。您可以手动检查该标志设置是否正确 – Mefhisto1 2015-08-05 09:48:49

1

与Heisa一样,但与WMI。 (代码是Powershell的,但可以很容易地移植到C#)

if ($svc = gwmi win32_service|?{$_.name -eq $svcname}) 
{ 
    try { 
     $null = $svc.change($svc.displayname,$svc.pathname,16,1,` 
     "Manual",$false,$svc.startname,$null,$null,$null,$null) 
     write-host "Change made" 
    catch { throw "Error: $_" } 
} else 
{ throw "Service $svcname not installed" } 

为PARAM描述参见MSDN: Service Change() method

相关问题