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

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

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

  1. 打开了管理工具“服务”

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

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

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

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

【问题讨论】:

    标签: c# windows-services permissions


    【解决方案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 方工具无法处理的文件,所以我的应用程序在这种情况下挂了。我的服务将监视该过程,如果应用程序挂起,则服务关闭应用程序并重新启动。所以在这里我的服务与我的应用程序以这种方式相交。
    猜你喜欢
    • 2019-01-18
    • 2017-12-27
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    相关资源
    最近更新 更多