问题
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