Windows 服务可以安装自己






4.97/5 (111投票s)
永远不要再使用 .NET SDK 附带的 InstallUtil.exe 实用程序。
引言
使用 .NET SDK 附带的 InstallUtil.exe 实用程序可能非常痛苦。它很少在 PATH 中,因此当您像我一样在 QA 和生产服务器上工作时,您可能需要寻找该实用程序。 安装 Windows 服务应该更容易。 在这篇短文中,我将向您展示一种让您的 Windows 服务自行安装的方法,而无需任何 InstallUtil.exe 。
假设
假设您的服务项目已经有一个服务安装程序、一个服务进程安装程序和一个派生自 System.Configuration.Install.Installer
的类。 如果没有,请查看 Mahmoud Nasr 关于 Windows 服务开发的精彩文章,然后回到这里。
关键信息
感谢 Reflector for .NET by Lutz Roeder, 很容易发现 InstallUtil.exe 实用程序是如何工作的。 在一些设置之后, InstallUtil.exe 工具跳到 System.Configuration.Install
命名空间中的 ManagedInstallerClass
中的名为 InstallHelper
的方法。 真正有趣的是,传递给 InstallUtil.exe 作为字符串数组的命令行参数随后直接传递给这个帮助器方法。
嗯,这让我想,“如果 InstallUtil.exe 所做的只是调用 ManagedInstallerClass
的 InstallHelper
方法,为什么我的服务可执行文件不能做同样的事情来通过命令安装自己呢?” 下面的小类让这样做变得很简单。
Using the Code
在您的服务可执行项目创建一个新的 CS 文件,其中包含以下代码。 如果您还没有,您可能还需要从全局程序集缓存中添加对 System.Configuration.Install.dll 的引用。
using System.Reflection;
using System.Configuration.Install;
namespace gotnet.biz.Utilities.WindowsServices
{
public static class SelfInstaller
{
private static readonly string _exePath =
Assembly.GetExecutingAssembly().Location;
public static bool InstallMe()
{
try
{
ManagedInstallerClass.InstallHelper(
new string[] { _exePath } );
}
catch
{
return false;
}
return true;
}
public static bool UninstallMe()
{
try
{
ManagedInstallerClass.InstallHelper(
new string[] { "/u", _exePath } );
}
catch
{
return false;
}
return true;
}
}
}
现在您需要为知道何时调用安装程序制定某种约定。 下面只是一个示例,说明您如何在 Main()
方法(即服务的入口点)中处理此问题。 我喜欢使用 -i
或 -install
参数来安装服务,使用 -u
或 -uninstall
来卸载服务的约定。 我还喜欢使用 -c
或 -console
来表示在控制台中启动应用程序,而不是作为服务。 然而,这是另一篇文章的主题。
using gotnet.biz.Utilities.WindowsServices;
namespace MyService.WinHost
{
static class Program
{
public static void Main( string[] args )
{
if (args != null && args.Length == 1 && args[0].Length > 1
&& (args[0][0] == '-' || args[0][0] == '/'))
{
switch (args[0].Substring( 1 ).ToLower())
{
default:
break;
case "install":
case "i":
SelfInstaller.InstallMe();
break;
case "uninstall":
case "u":
SelfInstaller.UninstallMe();
break;
case "console":
case "c":
MyConsoleHost.Launch();
break;
}
}
else
MyWinServiceHost.Launch();
}
}
}
现在,假设我的可执行文件名为 MyWinSvcHost.exe,我可以通过运行以下命令来调用安装程序
C:\> MyWinSvcHost.exe -install
或者要卸载我的服务,我将使用这个
C:\> MyWinSvcHost.exe -uninstall
其他想法
这段名为 SelfInstaller
的小代码充满了可能性。 例如,您可以将参数传递给 InstallMe
方法以传递给程序中的 ServiceProcessInstaller
。 也许用于启动服务的域名、用户名和密码可以从您的 Main()
方法传递到 ServiceProcessInstaller
。 酷吧? 我认为你会喜欢这样。
历史
- 2007 年 11 月 22 日 - 初次发布