Installer class that receives parameters used in the 'Install' method

痞子三分冷 提交于 2020-01-13 05:38:10

问题


I have a class inheriting from System.Configuration.Install.Installer class, and used to install a Windows Service. It looks like this:

[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);
    }
}

I have used the InstallUtil.exe utility for installing and uninstalling this service, and everything is working just fine.

Then I has to receive the user name and password as parameters (rather than hard coded), so I have changed the class and overridden the 'Install' method, and moved code section mentioned above from the constructor.

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);
}

Now, I'm installing the service again, using this:

InstallUtil.exe /UserName=UserName /Password=UserPassword Path...

The installation of the service is working great, with the desired user name and password. However, I do have now a problem with un-installing the service. I'm using the InstallUtil.exe /u, but the service is still there.

I read here a useful tip:

If you need to add installer instances to the Installers collection in the Install method, be sure to perform the same additions to the collection in the Uninstall method. However, you can avoid maintaining the collection in both methods if you add installer instances to the Installers collection in the class constructor for your custom installer.

I can't really understand what can solve this problem.

Any help will be most appreciated.

Elad


回答1:


* Solution *

Here is the solution I found, indeed according the link I have displayed above:

In the Uninstall() method I'm doing exactly the same like in the Install() method (besides subscribing the AfterInstall event), and then calling the base.Uninstall() method.

The method looks like this:

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);
}

Of course that the common code for both the methods should be wrapped into a single private method.

Now, in order to uninstall the service you should call InstallUtil.exe with the user name and the password, like this:

InstallUtil.exe /u /UserName=UserName /Password=UserPassword Path...

Good luck,

Elad




回答2:


From your link

If you override the Install method in a derived class, be sure to call the base class's Install method first in your derived method.

You are calling base.Install(...) last. Try calling it before doing any other work as the documentation suggests and see if that alleviates your issue.



来源:https://stackoverflow.com/questions/15672072/installer-class-that-receives-parameters-used-in-the-install-method

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!