运行安装包问题的C#Windows服务

时间:2011-04-02 11:04:56

标签: c# windows windows-services service

我设计了一个Windows服务,定期检查是否安装了特定的应用程序,当它发现它没有安装时,它从共享网络位置下载,该文件是一个无声的无人值守安装exe(自安装)

我在运行安装程序时遇到问题所以我决定不再尝试运行安装程序,而是运行一个小的hello world windows forms应用程序,只是为了看看这个简单的事情是否有效。

经过几个小时的困惑后,我终于发现hello world app确实在不同的用户下运行 - 特别是本地机器。在接下来的几个小时里,我发现我必须关闭UAC(Vista / 7)并允许该服务与桌面交互。在此之后,我终于在我的桌面上得到一个提示,即服务正在尝试运行某些内容,而我必须决定是否允许它。

当我按下允许时 - 我被带到另一个GUI(与我的桌面不同),之后hello world正常运行。

现在,虽然这肯定是一个进步,但我仍然远离在当前用户帐户下安装应用程序。

我遇到的一个问题是将Windows服务设置为以特定用户身份运行,当我在那种WS上使用installutil.exe时它会提示我输入用户名和密码,我输入了正确的(admin privilige)数据它无法安装。

我想要实现的是让Windows服务安装一个静默安装包而不以任何方式打断用户,测试静默安装包是net framework 2.0 - 我需要安装,好像用户自己点击它一样

我不需要任何代码(但这是受欢迎的),请指出我正确的方向,提前谢谢!

2 个答案:

答案 0 :(得分:1)

我不知道它是如何在C#中完成的,但我会解释这个概念。

当您在Windows服务中时,您的应用程序运行SYSTEM用户,因为应用程序甚至在执行任何登录之前都会运行。

此外,从win7本地服务帐户无法显示GUI,因为主要的安全问题,如导致应用程序运行cmd.exe任何类型的浏览器,允许用户执行他/她不想做的事情(我认为你可以绕过它,不确定,但不建议不管怎样,所以不要这样做。

所以你有两个选择:

  1. 创建另一个将在用户会话下运行的应用程序,您可以使用RPC(如.Net远程处理)与它进行通信。您可以将应用程序放在用户的启动中。

  2. 在我看来,更好的方法是使用CreateProcessAsUser()(我不知道它是如何在C#中调用的)。每个用户都有一个令牌,因为您是一个服务,您有权获得用户的主令牌,允许您在用户的帐户下创建进程。 CreateProcessAsUser()创建一个进程,它还获得一个令牌来以此用户身份运行该进程。

  3. 关于令牌的更多内容,对于CreateProcessAsUser,您需要获取用户的令牌。从Windows服务(仅限Windows服务)执行此操作的最简单方法是使用WTSQuestUserToken。您为该函数提供了用户会话的sessionID,并且您将获得一个主令牌。

    这种方法并不完美,但它很容易适用于大多数情况。如果在同一个sessionID(sessionID ==终端服务器会话ID)下有2个用户,则可以使用它,这可以使用资源管理器中的“运行方式”完成。但是我觉得我的答案太复杂了,所以如果你对WTSQueryUserToken()不够好,请告诉我,我会更彻底地解释(显然会更复杂)。

    祝你好运!

答案 1 :(得分:1)

你会发现为什么你会在我的答案herehere中看到你所描述的行为的详细解释,以防你好奇。

但无论如何,解决方案是要找到另一种方法。 Windows服务无法显示用户界面,也无法在特定用户的上下文中运行。对于你想做的事情,它们根本不是一个可行的选择。禁用UAC也是可接受的选项。

很难想象为什么首先需要从Windows服务中执行此操作。用户登录时运行的后台进程似乎是更好的方法。它根本没有任何接口,但它仍然可以弹出一个窗口,或者在用户选择时以其他方式与用户交互。

相关问题