Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何正常显示应用程序_C#_.net_Windows_Service_Process - Fatal编程技术网

C# 如何正常显示应用程序

C# 如何正常显示应用程序,c#,.net,windows,service,process,C#,.net,Windows,Service,Process,我正在Windows 7上创建一个复杂的服务,它从加载一个.exe应用程序开始。实现这一点的唯一方法是在Services.msc中启用“交互式服务检测”服务 作为一个测试应用程序,我添加了以下代码,它只是打开了系统计算器。但是,它的工作原理与预期不同。启动服务时,我首先收到以下消息: public partial class OpenCalculator : ServiceBase { public Process process; public Ope

我正在Windows 7上创建一个复杂的服务,它从加载一个.exe应用程序开始。实现这一点的唯一方法是在Services.msc中启用“交互式服务检测”服务

作为一个测试应用程序,我添加了以下代码,它只是打开了系统计算器。但是,它的工作原理与预期不同。启动服务时,我首先收到以下消息:

public partial class OpenCalculator : ServiceBase
    {
        public Process process;

        public OpenCalculator()
        {
            this.ServiceName = "Open Calculator";
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            start_calc();
        }

        protected override void OnStop()
        {
            process.Kill();
        }

        protected void start_calc()
        {
            try
            {
                process = new Process();
                process.StartInfo.FileName = @"C:\Windows\system32\calc.exe";
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.ErrorDialog = false;
                process.StartInfo.RedirectStandardError = true;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                process.Start();

                using (StreamWriter writer = File.AppendText("C:\\Users\\scaruana\\Desktop\\test.txt"))
                {
                    writer.WriteLine(process);
                }
            }
            catch (Exception ex)
            {
                using (StreamWriter writer = File.AppendText("C:\\Users\\scaruana\\Desktop\\test.txt"))
                {
                    writer.WriteLine(ex.Message);
                }
            }
        }
    }

单击“查看此消息”时,它会按预期加载计算器,但会打开蓝色全屏模式,并在其中包含计算器

我的问题基本上是:如何使应用程序自动显示,而不必提示用户“查看消息”,更重要的是,如何使应用程序正常显示,而不是在这个“交互式服务检测”沙箱中

这是我的示例服务的代码:

public partial class OpenCalculator : ServiceBase
    {
        public Process process;

        public OpenCalculator()
        {
            this.ServiceName = "Open Calculator";
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            start_calc();
        }

        protected override void OnStop()
        {
            process.Kill();
        }

        protected void start_calc()
        {
            try
            {
                process = new Process();
                process.StartInfo.FileName = @"C:\Windows\system32\calc.exe";
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.ErrorDialog = false;
                process.StartInfo.RedirectStandardError = true;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                process.Start();

                using (StreamWriter writer = File.AppendText("C:\\Users\\scaruana\\Desktop\\test.txt"))
                {
                    writer.WriteLine(process);
                }
            }
            catch (Exception ex)
            {
                using (StreamWriter writer = File.AppendText("C:\\Users\\scaruana\\Desktop\\test.txt"))
                {
                    writer.WriteLine(ex.Message);
                }
            }
        }
    }

服务在会话0中运行,您无法看到其桌面。交互式桌面托管在其他会话中。例如,第一次交互式登录在会话1中运行。这意味着服务无法在交互式桌面上直接显示UI

在旧版本的Windows(XP及更早版本)中,第一次交互式登录与服务共享会话0。因此,当您在服务控制管理器中启用“允许服务与桌面交互”选项时,该服务可以在交互桌面上显示UI。然而,所有这些都以Vista结束,因为它存在安全风险

因此,您需要启动一个新进程,特别是将其强制到登录的交互式用户的桌面上。这不容易做到。此MSDN博客文章介绍了您的选项:


现在,这就是如何从服务启动新流程,并将新流程放到交互式桌面上。但这几乎肯定是解决问题的错误方法。正如您通过阅读链接文章所看到的,这样做很复杂。问题的标准解决方案是在登录用户的桌面上运行交互式进程。在您的服务需要显示UI之前,这将一直处于隐藏状态。然后,该服务使用您首选的IPC机制与桌面应用程序进行通信,然后桌面应用程序显示UI。

这个问题让我非常沮丧,我终于解决了我的问题。是的,我已经设法将服务加载到GUI应用程序中,尽管每个人都说这是不可能的。不过有一个警告——“修复”可以被认为是利用了Windows中的漏洞,因为我使用的代码基本上通过了Vista和Windows7UAC。本质上,应用程序总是以完全权限执行,并绕过UAC

如果有人有同样的问题,您需要做的是遍历PC上已登录用户的列表,并选择在此会话(具有用户的桌面)中打开UI应用程序,而不是在会话0中打开UI应用程序,在会话0中服务应该运行(且没有桌面)

对于某些人来说,这可能不是一个解决方案,因为它不安全。但在我的情况下,安全不是一个主要问题,我只需要它工作(必须是一种武力服务)


希望这能帮助那些和我有同样问题的人。

请详细说明最后一部分好吗?为你的UI创建一个单独的桌面应用程序。例如,在登录时使用
HKLM\Software\Microsoft\Windows\CurrentVersion\Run
运行它。让它隐藏在背景中。当您的服务需要显示UI时,让它使用IPC与桌面应用程序联系,并指示桌面应用程序执行任何需要执行的操作。顺便说一句,我已经查看了您最近提出的所有问题,这些问题都归结为此答案中涉及的问题。我将尝试一下您的建议。您能提供一些关于服务和UI应用程序之间IPC的信息吗?到目前为止,我在使用服务尝试调用批处理文件或打开进程时所做的每一次尝试都没有成功。在.net中,您可以选择WCFOf当然我很感激,但是它并没有解决我的问题,而我所采取的方法确实解决了问题。因此,如果将来有人遇到同样的问题,那么与使用WCF和互操作性相比,上述方法应该可以更轻松地解决问题。你显然不喜欢它。再读一遍我的第三段。你就是这么做的。你似乎混淆了你所问问题的答案和你所实施的问题的具体解决方案。我很失望。你对第三段的看法是对的,但我并不是这么做的。我的方法简单得多,不涉及您链接的文章中建议的低级编程类型。我承认我错过了这一部分,因为我更多地关注了你提到IPC的最后一段:)我对你的答案感到满意,因为那篇文章是一种有效的方法,尽管可能需要更高的专业知识才能实现。你正在做那篇文章建议的事情。您正在指定的桌面上创建进程。