2

我有一个继承自 System.Configuration.Install.Installer 类的类,用于安装 Windows 服务。它看起来像这样:

[RunInstaller(true)]
public class HostInstaller : Installer
{
    private const string _serviceName = "My service name";
    private ServiceProcessInstaller _process;
    private ServiceInstaller _service;

    public HostInstaller()
    {
        _process = new ServiceProcessInstaller();
        _process.Account = ServiceAccount.User;
        _process.Username = "My user name";  // Hard coded
        _process.Password = "My password";   // Hard coded
        _service = new ServiceInstaller();
        _service.ServiceName = _serviceName;
        _service.Description = "My service description";
        _service.StartType = ServiceStartMode.Automatic;
        Installers.Add(_process);
        Installers.Add(_service);
    }
}

我使用 InstallUtil.exe 实用程序安装和卸载此服务,一切正常。

然后我必须接收用户名和密码作为参数(而不是硬编码),所以我更改了类并覆盖了“安装”方法,并从构造函数中移动了上面提到的代码部分。

public override void Install(System.Collections.IDictionary stateSaver)
{
    string userName = this.Context.Parameters["UserName"];
    if (userName == null)
    {
        throw new InstallException("Missing parameter 'UserName'");
    }

    string password = this.Context.Parameters["Password"];
    if (password == null)
    {
        throw new InstallException("Missing parameter 'Password'");
    }

    _process = new ServiceProcessInstaller();
    _process.Account = ServiceAccount.User;
    _process.Username = userName;
    _process.Password = password;
    _service = new ServiceInstaller();
    _service.ServiceName = _serviceName;
    _service.Description = "My service description";
    _service.StartType = ServiceStartMode.Automatic;
    Installers.Add(_process);
    Installers.Add(_service);

    base.Install(stateSaver);
}

现在,我再次安装服务,使用这个:

InstallUtil.exe /UserName=UserName /Password=UserPassword 路径...

使用所需的用户名和密码,该服务的安装运行良好。但是,我现在确实遇到了卸载服务的问题。我正在使用 InstallUtil.exe /u,但服务仍然存在。

我在这里读到了一个有用的提示:

如果您需要在 Install 方法中将安装程序实例添加到 Installers 集合,请务必在 Uninstall 方法中对集合执行相同的添加操作。但是,如果将安装程序实例添加到自定义安装程序的类构造函数中的 Installers 集合,则可以避免在这两种方法中维护集合。

我真的不明白什么可以解决这个问题。

任何帮助将不胜感激。

埃拉德

4

2 回答 2

1

* 解决方案 *

这是我找到的解决方案,确实是根据我上面显示的链接:

在 Uninstall() 方法中,我所做的与在 Install() 方法中的操作完全相同(除了订阅 AfterInstall 事件),然后调用 base.Uninstall() 方法。

该方法如下所示:

public override void Uninstall(System.Collections.IDictionary stateSaver)
{
    string userName = this.Context.Parameters["UserName"];
    if (userName == null)
    {
        throw new InstallException("Missing parameter 'UserName'");
    }

    string password = this.Context.Parameters["Password"];
    if (password == null)
    {
        throw new InstallException("Missing parameter 'Password'");
    }

    _process = new ServiceProcessInstaller();
    _process.Account = ServiceAccount.User;
    _process.Username = userName;
    _process.Password = password;
    _service = new ServiceInstaller();
    _service.ServiceName = _serviceName;
    _service.Description = "My service description";
    _service.StartType = ServiceStartMode.Automatic;
    Installers.Add(_process);
    Installers.Add(_service);

    base.Uninstall(stateSaver);
}

当然,这两种方法的公共代码都应该包装到一个私有方法中。

现在,为了卸载服务,您应该使用用户名和密码调用 InstallUtil.exe,如下所示:

InstallUtil.exe /u /UserName=UserName /Password=UserPassword 路径...

祝你好运,

埃拉德

于 2013-04-02T22:26:41.903 回答
0

从你的链接

如果在派生类中重写 Install 方法,请确保在派生方法中首先调用基类的 Install 方法。

base.Install(...)最后打电话了。按照文档的建议,在执行任何其他工作之前尝试调用它,看看是否可以缓解您的问题。

于 2013-03-28T00:46:21.513 回答