Install a .NET windows service without InstallUtil.exe
You can always fall back to the good old WinAPI calls, although the amount of work involved is non-trivial. There is no requirement that .NET services be installed via a .NET-aware mechanism.
To install:
- Open the service manager via
OpenSCManager
. - Call
CreateService
to register the service. - Optionally call
ChangeServiceConfig2
to set a description. - Close the service and service manager handles with
CloseServiceHandle
.
To uninstall:
- Open the service manager via
OpenSCManager
. - Open the service using
OpenService
. - Delete the service by calling
DeleteService
on the handle returned byOpenService
. - Close the service and service manager handles with
CloseServiceHandle
.
The main reason I prefer this over using the ServiceInstaller
/ServiceProcessInstaller
is that you can register the service with your own custom command line arguments. For example, you might register it as "MyApp.exe -service"
, then if the user runs your app without any arguments you could offer them a UI to install/remove the service.
Running Reflector on ServiceInstaller
can fill in the details missing from this brief explanation.
P.S. Clearly this won't have "the same effect as calling: InstallUtil MyService.exe" - in particular, you won't be able to uninstall using InstallUtil. But it seems that perhaps this wasn't an actual stringent requirement for you.
Yes, that is fully possible (i.e. I do exactly this); you just need to reference the right dll (System.ServiceProcess.dll) and add an installer class...
Here's an example:
[RunInstaller(true)]
public sealed class MyServiceInstallerProcess : ServiceProcessInstaller
{
public MyServiceInstallerProcess()
{
this.Account = ServiceAccount.NetworkService;
}
}
[RunInstaller(true)]
public sealed class MyServiceInstaller : ServiceInstaller
{
public MyServiceInstaller()
{
this.Description = "Service Description";
this.DisplayName = "Service Name";
this.ServiceName = "ServiceName";
this.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
}
}
static void Install(bool undo, string[] args)
{
try
{
Console.WriteLine(undo ? "uninstalling" : "installing");
using (AssemblyInstaller inst = new AssemblyInstaller(typeof(Program).Assembly, args))
{
IDictionary state = new Hashtable();
inst.UseNewContext = true;
try
{
if (undo)
{
inst.Uninstall(state);
}
else
{
inst.Install(state);
inst.Commit(state);
}
}
catch
{
try
{
inst.Rollback(state);
}
catch { }
throw;
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
Take a look at the InstallHelper method of the ManagedInstaller class. You can install a service using:
string[] args;
ManagedInstallerClass.InstallHelper(args);
This is exactly what InstallUtil does. The arguments are the same as for InstallUtil.
The benefits of this method are that it involves no messing in the registry, and it uses the same mechanism as InstallUtil.