Can the Service Installer class run in a different Assembly?

怎甘沉沦 提交于 2019-12-11 00:16:50

问题


I have a custom Installer class that is used when installing my Windows Service. Stripped down to the necessary details the class looks like this.

[RunInstaller(true)]
public class MyWindowsServiceInstaller : Installer
{
    public MyWindowsServiceInstaller()
    {
        ServiceProcessInstaller processInstaller = new ServiceProcessInstaller();
        ServiceInstaller serviceInstaller = new ServiceInstaller();

        processInstaller.Account = ServiceAccount.LocalSystem;

        serviceInstaller.DisplayName = Program.ServiceDetails.Name;
        serviceInstaller.Description = Program.ServiceDetails.Description;

        //Must be the same as what was set in Program's constructor
        serviceInstaller.ServiceName = Program.ServiceDetails.Name;

        Installers.Add(processInstaller);
        Installers.Add(serviceInstaller);
    }
}

The service is then installed through code by calling the following class, depending on arguments passed into the service, like so. This is called from inside of Main.

using (ServiceHandler serviceHandler = new ServiceHandler(program.ModuleName, typeof(Program).Assembly))
{
    serviceHandler.InstallService();
}

Where the ServiceHandler class is (again stripped down to remove noise).

public class ServiceHandler : IDisposable
{
    private ServiceController _serviceController;
    private AssemblyInstaller _assemblyInstaller;

    public ServiceHandler(string serviceName, Assembly assembly)
    {
        _serviceController = new ServiceController(serviceName);

        _assemblyInstaller = new AssemblyInstaller(assembly, null);
        _assemblyInstaller.UseNewContext = true;
    }

    public void InstallService()
    {
        if (IsServiceInstalled())
        {
            return;
        }

        IDictionary state = new Hashtable();
        try
        {
            _assemblyInstaller.Install(state);
            _assemblyInstaller.Commit(state);
        }
        catch
        {
            try
            {
                _assemblyInstaller.Rollback(state);
            }
            catch { }
            throw;
        }
    }

    public bool IsServiceInstalled()
    {
        try
        {
            ServiceControllerStatus status = _serviceController.Status;
        }
        catch
        {
            return false;
        }

        return true;
    }
}

However, at the moment all of our services use the same MyWindowsServiceInstaller but copied into each project separately. To resolve this I was going to move that class to a common assembly with some other functionality (and remove the coupling of the class with Program) but I'm not sure if it's possible to have the Installer in another assembly.

Is this possible? If so how do I go about it?


I imagine another problem with my approach is the typeof(Program).Assembly call to create the ServiceHandler but I'm not sure.


回答1:


Installer looks into the assembly and looking for [RunInstaller(true)] attribute. Only think you should do: Mark for installer witch is your installer class. Put an inherited empty class into your main assembly.

Common Assembly:

//[RunInstaller(true)] <<-- REMOVE this
public class MyWindowsServiceInstaller : Installer
{
   public MyWindowsServiceInstaller(){
    ServiceProcessInstaller processInstaller = new 
    ServiceProcessInstaller();
    ServiceInstaller serviceInstaller = new ServiceInstaller();

    processInstaller.Account = ServiceAccount.LocalSystem;

    serviceInstaller.DisplayName = Program.ServiceDetails.Name;
    serviceInstaller.Description = Program.ServiceDetails.Description;

    //Must be the same as what was set in Program's constructor
    serviceInstaller.ServiceName = Program.ServiceDetails.Name;

    Installers.Add(processInstaller);
    Installers.Add(serviceInstaller);
    }
}

Main assembly

[RunInstaller(true)] // <<-- put it here
public class ProjectInstaller : MyWindowsServiceInstaller { }


来源:https://stackoverflow.com/questions/49298429/can-the-service-installer-class-run-in-a-different-assembly

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