从 Windows 服务启动 GUI 应用程序 - 方法
Starting GUI application from Windows Service - Approaches
注意:尽管看起来是同一问题的另一个问题,但事实并非如此,但选择正确的标题似乎很难,因此欢迎更合适的标题更改。
我正在尝试解决从 Windows 7 Embedded(POS 就绪)上的服务应用程序启动 GUI 应用程序(Windows Forms,.NET)的问题,并且遇到了几种解决方案,但其中 none 有效,但我在此过程中发现了一个例外:使用批处理文件作为辅助文件。
背景:
有几个像 this 这样的 post 描述了为什么它被删除和保护,我理解 session 0 隔离,但在深入讨论为什么不应该这样做之前,我我只是想解决这个问题,因为我不喜欢我们公司目前使用的解决方案。
我将使用单词 "actual app" 表示我尝试过的两个 GUI 应用程序 运行。一个是 Windows Forms .NET exe,第二个是 Adobe AIR 构建 exe 应用程序。
我已成功设置测试服务并使用两个帐户进行了测试:
- 运行 本地系统帐户下的一项服务(有和没有 "Interact with desktop" 选项...)
- 运行 管理员帐户下的服务 -> 这种方法不允许使用 CreateProcessAsUser,因为它已经在用户 session
中
在本地系统帐户下,它按预期工作,我已经成功执行了 CreateProcessAsUser" 命令,如图 here by murrayu and used his helper class implementation,但没有成功。虽然实际应用程序在用户帐户下在 GUI 中启动,但它要么无法启动 (AIR),或者它有问题和错误,主要是存在拒绝访问异常(.NET 应用程序)。
在 Administrator 帐户下,使用 CreateProcessAsUser 的解决方案并不像提到的那样有效,而是使用方法 B(代码在 post 末尾) ,它适用于一个应用程序启动另一个应用程序,但没有用。正如预期的那样,不存在 GUI。
第三次尝试,解决方案包括服务将调用的帮助程序应用程序,然后启动实际的应用程序。使用本地系统帐户和 CreateProcessAsUser 对此进行测试,然后在助手应用程序中调用方法 B,导致与第一次测试相同的行为,其中服务调用实际应用程序。
奇怪的是,使用 CreateProcessAsUser 打开 Notepad.exe、cmd.exe、calc.exe 效果很好。
由于命令行有效,我进入了那个兔子洞:
第四次尝试,解决方案包括一个批处理文件,其中包含一个命令:
START D:\TESTAPP\DotNetApp.lnk
注意是指向快捷方式,直接调用exe是不行的。
令我惊讶的是,这种方法奏效了!实际应用程序启动时就像通过手动执行文件定期启动一样。
现在最让我烦恼的是 - 有什么我还没有找到或尝试过的吗?我错过了什么重要的事情吗? .NET 应用程序 运行 在报告访问被拒绝异常时使用具有完全权限的管理员帐户,如果从文件夹手动执行,即使在用户帐户(受限)下也能正常工作,所以看起来真的没有什么特别之处就像 运行 来自服务时的错误原因。
最重要的,或者说最令人疑惑的问题:命令行/批处理的作用是什么?是否可以在辅助应用程序中对其行为/解决方案进行编程,或者更好的是,直接在服务本身中进行编程?
此外,如果希望有一个服务处理 GUI 应用程序,并且不希望依赖 Startup/Autorun,什么是更好的解决方案?
附录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();
}
任何见解将不胜感激。
是否有令人信服的理由让服务启动 UI 应用程序?我的意思是,由于 UI 应用程序用于用户交互,服务如何知道用户在任何给定时间是否真的坐在计算机前?是什么触发服务启动应用程序?如果用户关闭应用程序,是什么触发应用程序重新启动 UI?为什么用户不能直接启动应用程序?应用无法直接为table带来什么服务?
我们使用 Windows 服务作为我们项目的一部分。它在后台 24/7/365 运行。它处于稳定状态,直到用户打开 UI 应用程序。在 UI 初始化期间,它会建立到它维护的服务的连接,直到 UI 关闭。当用户与 UI 交互时,命令会发送到幕后的服务,指导服务做什么。
关键是,有什么理由不能让您的服务以这种方式运行吗?代替服务打开应用程序,让用户在她准备好时打开应用程序,然后让应用程序通过 IPC 连接到服务以促进任何必要的 UI-服务交互。您甚至可以提供允许应用折叠到系统托盘的功能,有效地隐藏它,直到用户需要再次访问它。病毒扫描软件就是这样工作的,我们已经在我们的工具版本中采用了这种方法
HTH
经过一天的尝试和错误编码,我已经设法调试并找出导致解决方案中使用 pInvoke 到 CreateProcessAsUser()
的错误的原因advapi32.dll 模块中的方法。
如问题本身所述,theres a topic on how to invoke GUI process from session 0 to current's user session 使用 CreateProcessAsUser() 方法。
我错误地忽略了它的工作目录路径,所以当调用 GUI 进程时一些相对路径没有工作,导致 StartProcessAsCurrentUser
包装器的 [=11] 的其他完全和很好的工作实现=] pInvoke.
应用示例的正确调用是:
StartProcessAsCurrentUser(@"D:\Presentations\GUI.exe", null, @"D:\Presentations", true);
(其中 Presentations\GUI.exe 是一个示例应用程序。null 参数是可选参数参数,第三个参数是工作目录,我错误地总是将其调用为 null。
我想把它留在这里可能会有帮助,因为关于从服务或会话 0 调用 GUI 应用程序,甚至在远程主机上远程使用 ManagementClass instance method InvokeMethod("Create", {0});
的主题确实不多,这工作方式几乎相同。
注意:尽管看起来是同一问题的另一个问题,但事实并非如此,但选择正确的标题似乎很难,因此欢迎更合适的标题更改。
我正在尝试解决从 Windows 7 Embedded(POS 就绪)上的服务应用程序启动 GUI 应用程序(Windows Forms,.NET)的问题,并且遇到了几种解决方案,但其中 none 有效,但我在此过程中发现了一个例外:使用批处理文件作为辅助文件。
背景: 有几个像 this 这样的 post 描述了为什么它被删除和保护,我理解 session 0 隔离,但在深入讨论为什么不应该这样做之前,我我只是想解决这个问题,因为我不喜欢我们公司目前使用的解决方案。
我将使用单词 "actual app" 表示我尝试过的两个 GUI 应用程序 运行。一个是 Windows Forms .NET exe,第二个是 Adobe AIR 构建 exe 应用程序。
我已成功设置测试服务并使用两个帐户进行了测试:
- 运行 本地系统帐户下的一项服务(有和没有 "Interact with desktop" 选项...)
- 运行 管理员帐户下的服务 -> 这种方法不允许使用 CreateProcessAsUser,因为它已经在用户 session 中
在本地系统帐户下,它按预期工作,我已经成功执行了 CreateProcessAsUser" 命令,如图 here by murrayu and used his helper class implementation,但没有成功。虽然实际应用程序在用户帐户下在 GUI 中启动,但它要么无法启动 (AIR),或者它有问题和错误,主要是存在拒绝访问异常(.NET 应用程序)。
在 Administrator 帐户下,使用 CreateProcessAsUser 的解决方案并不像提到的那样有效,而是使用方法 B(代码在 post 末尾) ,它适用于一个应用程序启动另一个应用程序,但没有用。正如预期的那样,不存在 GUI。
第三次尝试,解决方案包括服务将调用的帮助程序应用程序,然后启动实际的应用程序。使用本地系统帐户和 CreateProcessAsUser 对此进行测试,然后在助手应用程序中调用方法 B,导致与第一次测试相同的行为,其中服务调用实际应用程序。
奇怪的是,使用 CreateProcessAsUser 打开 Notepad.exe、cmd.exe、calc.exe 效果很好。
由于命令行有效,我进入了那个兔子洞: 第四次尝试,解决方案包括一个批处理文件,其中包含一个命令:
START D:\TESTAPP\DotNetApp.lnk
注意是指向快捷方式,直接调用exe是不行的。
令我惊讶的是,这种方法奏效了!实际应用程序启动时就像通过手动执行文件定期启动一样。
现在最让我烦恼的是 - 有什么我还没有找到或尝试过的吗?我错过了什么重要的事情吗? .NET 应用程序 运行 在报告访问被拒绝异常时使用具有完全权限的管理员帐户,如果从文件夹手动执行,即使在用户帐户(受限)下也能正常工作,所以看起来真的没有什么特别之处就像 运行 来自服务时的错误原因。
最重要的,或者说最令人疑惑的问题:命令行/批处理的作用是什么?是否可以在辅助应用程序中对其行为/解决方案进行编程,或者更好的是,直接在服务本身中进行编程?
此外,如果希望有一个服务处理 GUI 应用程序,并且不希望依赖 Startup/Autorun,什么是更好的解决方案?
附录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();
}
任何见解将不胜感激。
是否有令人信服的理由让服务启动 UI 应用程序?我的意思是,由于 UI 应用程序用于用户交互,服务如何知道用户在任何给定时间是否真的坐在计算机前?是什么触发服务启动应用程序?如果用户关闭应用程序,是什么触发应用程序重新启动 UI?为什么用户不能直接启动应用程序?应用无法直接为table带来什么服务?
我们使用 Windows 服务作为我们项目的一部分。它在后台 24/7/365 运行。它处于稳定状态,直到用户打开 UI 应用程序。在 UI 初始化期间,它会建立到它维护的服务的连接,直到 UI 关闭。当用户与 UI 交互时,命令会发送到幕后的服务,指导服务做什么。
关键是,有什么理由不能让您的服务以这种方式运行吗?代替服务打开应用程序,让用户在她准备好时打开应用程序,然后让应用程序通过 IPC 连接到服务以促进任何必要的 UI-服务交互。您甚至可以提供允许应用折叠到系统托盘的功能,有效地隐藏它,直到用户需要再次访问它。病毒扫描软件就是这样工作的,我们已经在我们的工具版本中采用了这种方法
HTH
经过一天的尝试和错误编码,我已经设法调试并找出导致解决方案中使用 pInvoke 到 CreateProcessAsUser()
的错误的原因advapi32.dll 模块中的方法。
如问题本身所述,theres a topic on how to invoke GUI process from session 0 to current's user session 使用 CreateProcessAsUser() 方法。
我错误地忽略了它的工作目录路径,所以当调用 GUI 进程时一些相对路径没有工作,导致 StartProcessAsCurrentUser
包装器的 [=11] 的其他完全和很好的工作实现=] pInvoke.
应用示例的正确调用是:
StartProcessAsCurrentUser(@"D:\Presentations\GUI.exe", null, @"D:\Presentations", true);
(其中 Presentations\GUI.exe 是一个示例应用程序。null 参数是可选参数参数,第三个参数是工作目录,我错误地总是将其调用为 null。
我想把它留在这里可能会有帮助,因为关于从服务或会话 0 调用 GUI 应用程序,甚至在远程主机上远程使用 ManagementClass instance method InvokeMethod("Create", {0});
的主题确实不多,这工作方式几乎相同。