从Windows服务启动GUI应用程序-方法

jxct1oxe  于 2023-10-22  发布在  Windows
关注(0)|答案(2)|浏览(230)
  • 注意:* 尽管出现了同一问题的另一个问题,但它不是,但选择正确的标题似乎很难,所以更合适的标题变化是受欢迎的。

我试图解决从Windows 7 Embedded(POS就绪)上的服务应用程序启动GUI应用程序(Windows窗体,.NET)的问题,并遇到了几个解决方案,但没有一个工作,除了我沿着发现的一个例外:使用批处理文件作为帮助文件。

  • 背景:* 有几个这样的帖子描述了为什么这已经被删除和保护,我理解会话0隔离,但在任何辩论之前,为什么不应该这样做,我只是想让我的头周围,因为我不喜欢我们公司正在使用的当前解决方案。
  • 我将使用“实际应用程序”这两个GUI应用程序,我已经尝试运行。一个是Windows Forms .NET exe,第二个是Adobe AIR build exe应用程序。

我已经成功地设置了一个测试服务,并使用两个帐户进行了测试:

  • 在本地系统帐户下运行服务(使用和不使用“与桌面交互”选项.)
  • 在管理员帐户下运行服务->此方法不允许使用已在用户会话中的JavaProcessAsUser

在本地系统帐户下,它按预期工作,我已经成功地执行了“进程作为用户”命令,如here by murrayu and used his helper class implementation所示,但没有成功。虽然实际的应用程序在用户帐户下在GUI中启动,但它要么不启动(AIR),要么有问题和错误,主要是存在拒绝访问异常(.NET应用程序)。
在管理员帐户下,使用“以进程为用户”的解决方案不能像上面提到的那样工作,但是使用方法 B(在帖子末尾的代码),这对于一个应用程序启动另一个应用程序很好,没有工作。在某种程度上,不存在GUI,正如预期的那样。
第三次尝试,解决方案包括服务将调用的助手应用程序,然后启动实际的应用程序。使用本地系统帐户和服务ProcessAsUser进行测试,然后在助手应用程序中调用方法 B,结果与第一次测试中的行为相同,其中服务调用实际应用程序。
奇怪的是,使用OpenProcessAsUser打开Notepad.exe、Notepad.exe、calc.exe工作得很好。
由于命令行工作,我去了那个兔子洞:第四次尝试,解决方案包含一个批处理文件,其中包含一个命令:
START D:\TESTAPP\DotNetApp.lnk
请注意,它指向快捷方式,因为直接调用exe不起作用。

**令人惊讶的是,这种方法奏效了!**实际的应用程序启动,就像通过手动执行文件定期启动一样。

现在最让我烦恼的是--有什么我还没有发现或尝试过的吗?我错过了什么重要的事吗?.NET应用程序是使用具有完全权限的管理员帐户运行的,当它报告Access denied exceptions时,如果手动执行表单文件夹,即使在User account(受限)下也可以正常工作,所以它真的没有什么特别之处,看起来像是从服务运行时错误的原因。
最重要的,或者说最令人困惑的问题是:命令行/批处理做了什么使它工作?有没有可能在助手应用程序中编程它的行为/解决方案,或者更好的是,直接在服务本身中编程?
此外,当想要有一个服务处理GUI应用程序,并依赖于启动/自动运行是不可取的,什么会是更好的解决方案?
附录 B

public static void ElevatedExecute(string processName, string command, bool useAdminElevationRights = false)
        {
            Process process = new Process();
            process.StartInfo = new ProcessStartInfo(processName, command);
            if (useAdminElevationRights)
            {
                SecureString ssPwd = new SecureString();
                process.StartInfo.UserName = "Administrator";
                string tmpPass = ADMIN_PASSWORD;
                for (int x = 0; x < tmpPass.Length; x++)
                    ssPwd.AppendChar(tmpPass[x]);
                process.StartInfo.Password = ssPwd;
            }
            process.StartInfo.UseShellExecute = false;
            process.Start();
        }

任何见解都将受到高度赞赏。

fhg3lkii

fhg3lkii1#

经过一天的试错编码,我已经成功地调试并找出了在advapi32.dll模块中使用pocketto**CreateProcessAsUser()**方法导致解决方案错误的原因。
正如问题本身所述,theres a topic on how to invoke GUI process from session 0 to current's user session使用了ProcessAsUser()方法。
我错误地忽略了它的工作目录路径,所以当GUI进程被调用时,一些相对路径不起作用,导致CreateProcessAsUser()封装器的StartProcessAsCurrentUser封装器的完全和良好的工作实现。
应用程序示例的正确调用是:

StartProcessAsCurrentUser(@"D:\Presentations\GUI.exe", null, @"D:\Presentations", true);

(其中Presentations\GUI.exe是示例应用程序。null参数是可选的arguments参数,第三个参数是工作目录,我错误地总是调用为null。
我想把它留在这里可能会有帮助,因为关于从服务或会话0调用GUI应用程序,甚至在远程主机上远程使用ManagementClass instance method InvokeMethod("Create", {0});(其工作方式几乎相同)的主题并不多。

kmpatx3s

kmpatx3s2#

是否有令人信服的理由让服务启动UI应用程序?我的意思是,既然UI应用程序是用于用户交互的,那么该服务如何知道用户是否在任何给定的时间坐在电脑前?什么触发服务启动应用程序?如果用户关闭应用程序,什么触发应用程序重新启动UI?为什么用户不能直接启动应用程序?什么是服务带来的表,应用程序不能直接做?
我们使用Windows服务作为我们项目的一部分。它在后台运行24/7/365。它处于稳定状态,直到用户打开UI应用程序。在UI初始化过程中,它建立到服务的连接,并一直保持该连接,直到UI关闭。当用户与UI交互时,命令被发送到后台的服务,指导服务做什么。
关键是,你有没有理由不能让你的服务以这种方式运行?不是服务打开应用,而是让用户在准备好的时候打开应用,然后让应用通过IPC连接到服务,以促进任何必要的UI-服务交互。您甚至可以提供允许应用程序折叠到系统托盘的功能,有效地隐藏它,直到用户需要再次访问它。病毒扫描软件就是这样工作的,我们已经在我们的工具版本中采用了这种方法
HTH

相关问题