1

注意:尽管出现了同一问题的另一个问题,但事实并非如此,但选择正确的标题似乎很难,因此欢迎更合适的标题更改。

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

背景: 有几篇这样的帖子描述了为什么它已被删除和保护,我理解会话 0 隔离,但在任何辩论深入探讨为什么不应该这样做之前,我只是想弄清楚它,因为我不喜欢我们公司目前使用的解决方案。

我将使用“实际应用程序”一词,它代表我尝试运行的两个 GUI 应用程序。一个是 Windows Forms .NET exe,第二个是 Adob​​e AIR build exe 应用程序。

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

  • 在本地系统帐户下运行服务(带有和不带有“与桌面交互”选项...)
  • 在管理员帐户下运行服务-> 这种方法不允许使用 CreateProcessAsUser,因为它已经在用户会话中

在本地系统帐户下,它按预期工作,我已经成功执行了 murrayu 此处显示的 CreateProcessAsUser" 命令并使用了他的帮助程序类实现,但没有成功。虽然实际应用程序在用户帐户下的 GUI 中启动,但它要么没有启动(AIR),或者它有问题和错误,主要是存在访问被拒绝异常(.NET 应用程序)。

在管理员帐户下,使用 CreateProcessAsUser 的解决方案无法正常工作,但使用方法B(帖子末尾的代码),该方法适用于一个应用程序启动另一个应用程序,但无法正常工作。正如预期的那样,没有 GUI 存在。

第三次尝试,解决方案包括服务将调用的帮助应用程序,然后启动实际应用程序。使用本地系统帐户和 CreateProcessAsUser 对此进行测试,然后在帮助应用程序中调用方法B,结果与第一次测试中的行为相同,其中服务调用了实际应用程序。

奇怪的是,使用 CreateProcessAsUser 打开 Notepad.exe、cmd.exe、calc.exe 工作正常。

由于命令行工作,我去了那个兔子洞:第四次尝试,解决方案包括一个批处理文件,其中包括一个命令:

START D:\TESTAPP\DotNetApp.lnk

请注意,它指向快捷方式,因为直接调用 exe 不起作用。

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

现在最让我烦恼的是 - 有什么我还没有找到或尝试过的东西吗?我错过了什么重要的事情吗?.NET 应用程序在报告访问被拒绝异常时使用具有完全权限的管理员帐户运行,并且如果在表单文件夹中手动执行,即使在用户帐户(受限)下也可以正常工作,因此它确实没有什么特别之处,这似乎是导致从服务运行时的错误。

最重要或最想知道的问题是:命令行/批处理是如何使它工作的?是否可以在帮助应用程序中编程它的行为/解决方案,或者更好的是,直接在服务本身中编程?

此外,当想要一个服务处理 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();
        }

任何见解将不胜感激。

4

2 回答 2

0

是否有令人信服的理由让服务启动 UI 应用程序?我的意思是,由于 UI 应用程序是为用户交互而设计的,那么服务如何知道用户是否真的在任何给定时间坐在电脑前?什么触发服务启动应用程序?如果用户关闭应用程序,是什么触发应用程序重新启动 UI?为什么用户不能直接启动应用程序?应用程序无法直接完成的服务是什么?

我们使用 Windows 服务作为我们项目的一部分。它在后台 24/7/365 运行。它处于稳定状态,直到用户打开 UI 应用程序。在 UI 初始化期间,它会建立与它所维护的服务的连接,直到 UI 关闭。当用户与 UI 交互时,命令被发送到幕后的服务,指示服务做什么。

关键是,您有什么理由不能让您的服务以这种方式运行?与其让服务打开应用程序,不如让用户在准备好时打开应用程序,然后让应用程序通过 IPC 连接到服务,以促进任何必要的 UI 服务交互。您甚至可以提供允许应用折叠到系统托盘的功能,从而有效地隐藏它,直到用户需要再次访问它。病毒扫描软件以这种方式工作,我们在我们的工具版本中采用了这种方法

高温高压

于 2020-05-20T00:35:07.543 回答
0

经过一天的反复试验和错误编码,我已经设法调试并找出导致解决方案错误的原因,CreateProcessAsUser()方法是在advapi32.dll模块中使用 pInvoke 方法。

如问题本身所述,有一个关于如何使用 CreateProcessAsUser() 方法从会话 0 调用 GUI 进程到当前用户会话的主题。

我错误地忽略了它的工作目录路径,因此在调用 GUI 进程时一些相对路径没有工作,导致pInvokeStartProcessAsCurrentUser包装器的其他完全和很好的工作实现。CreateProcessAsUser()

应用程序示例的正确调用是:

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

(其中 Presentations\GUI.exe 是一个示例应用程序。null 参数是可选参数参数,第三个参数是工作目录,我错误地总是将其调用为 null。

我认为把它留在这里可能会有所帮助,因为实际上没有太多关于从服务或会话 0 调用 GUI 应用程序的主题,或者甚至ManagementClass instance method InvokeMethod("Create", {0});在远程主机上远程使用,其工作方式几乎相同。

于 2020-05-22T16:37:05.493 回答