如何在代码中配置我的 windows 服务以访问桌面?

Posted

技术标签:

【中文标题】如何在代码中配置我的 windows 服务以访问桌面?【英文标题】:How can I configure my windows service in the code to access the desktop? 【发布时间】:2010-12-29 01:36:46 【问题描述】:

我创建了一个 Windows 服务。我想从此服务中打开一些基于 Windows 的应用程序。

但我的 Windows 服务无法启动桌面应用程序。要启用访问权限,我必须执行以下步骤:

    打开了管理工具“服务”

    右键单击我的服务,必须选择“属性”

    然后在“登录”选项卡中,选择“允许服务与桌面交互”。

之后我的服务可以打开所需的基于窗口的进程。

我可以在代码(C#)中配置我的windows服务来访问桌面,这样我就不必在安装后手动更改访问权限了吗?

【问题讨论】:

【参考方案1】:

只是...不要。这不是服务的工作。对于这项工作,您应该使用一个用户应用程序(可能在他们的启动中),该应用程序(如有必要)通过 IPC 与服务进行通信。我相信计划是在某个时候使 UI 无法从服务中使用(从 Vista 开始?我在 很久 之前就停止了服务桌面)。

注意事项:

如果您有多个用户登录(快速用户切换)怎么办? 如果您有多个 RDP 会话怎么办?

您所提议的内容仅真正扩展到 1,如果您认为“会话 0”在某些系统上保留供管理员使用(因此交互式用户不是必要在会话 0)。

【讨论】:

我不同意。当通过服务自动化应用程序时,必须为某些应用程序设置允许桌面访问的标志(例如,当唯一的交互方式是通过剪贴板时)。当然,扩展可能是个问题,但不能扩展的解决方案通常总比没有解决方案好(因为可扩展性并不总是必需的)。 那么:不要通过服务自动化应用程序。在用户会话中使用与服务交谈的应用。我在上面的答案中说过。这可能是一个稍微复杂的解决方案,但它是正确的解决方案。 我不会说一件事是对的,另一件事是错的。考虑使用现有应用程序执行诸如自动打印/转换文档之类的任务的服务。通常你不能让应用程序(MS Office、OpenOffice、旧版 WordPerfect 等)监听服务。当一切都由您的服务控制时,您甚至可以并行创建多个会话,而完全不需要交互式用户,因此它非常适合在服务器上运行。当然,命令行工具更适合此类工作,但您并非总是可以选择。 我会:在这里看到“重要”:msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx 但这是关于显示用户界面的服务。那是另一个故事,显然不是。【参考方案2】:

在 .NET 中,您可以覆盖服务安装程序类的 OnCommited 方法来配置服务以访问桌面。代码如下所示:

[RunInstaller(true)]
public partial class ProjectInstaller : Installer

    private ServiceProcessInstaller serviceProcessInstaller;
    private ServiceInstaller serviceInstaller;

    public ProjectInstaller()
    
        InitializeComponent();

        // adjust configuration to whatever is needed
        serviceInstaller = new ServiceInstaller();
        serviceInstaller.ServiceName = "My Service";
        serviceInstaller.DisplayName = "My Service";
        serviceInstaller.StartType = ServiceStartMode.Manual;
        this.Installers.Add(serviceInstaller);

        serviceProcessInstaller = new ServiceProcessInstaller();
        serviceProcessInstaller.Account = 
            System.ServiceProcess.ServiceAccount.LocalSystem;
        serviceProcessInstaller.Password = null;
        serviceProcessInstaller.Username = null;
        this.Installers.Add(serviceProcessInstaller);
    

    protected override void OnCommitted(IDictionary savedState)
    
        base.OnCommitted(savedState);

        // The following code sets the flag to allow desktop interaction 
        // for the service
        //
        using (RegistryKey ckey = 
            Registry.LocalMachine.OpenSubKey(
                @"SYSTEM\CurrentControlSet\Services\My Service", true))
        
            if (ckey != null && ckey.GetValue("Type") != null)
            
                ckey.SetValue("Type", (((int)ckey.GetValue("Type")) | 256));
            
        
    

【讨论】:

重新对/错;在这里看到“重要”:msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx 感谢 Marc Gravell。不错的文章,也是实现需求的简单方法。但是现在我的上级不允许我改变结构,这就是我试图解决这个问题的原因。 现在我向您解释我的服务是如何工作的,以便您了解我的要求。我的应用程序处理文档。为了完成这项任务,我使用了一些 3rd 方工具,如 adobe 和 Zprint。有时我们会得到这些 3rd 方工具无法处理的文件,所以我的应用程序在这种情况下挂了。我的服务将监视该过程,如果应用程序挂起,则服务关闭应用程序并重新启动。所以在这里我的服务与我的应用程序以这种方式相交。

以上是关于如何在代码中配置我的 windows 服务以访问桌面?的主要内容,如果未能解决你的问题,请参考以下文章

在 Ubuntu 上配置 SFTP 服务器以使用 PhpStorm 远程访问

如何在windows服务器中使用syslog功能

IDX10803:无法创建以获取配置

如何验证我的 Cloud Run 服务以访问 GSuite 用户的 gmail 消息?

如何在windows上配置并运行Nginx

如何在Windows上配置并运行Nginx