Install windows service without InstallUtil.exe

前端 未结 8 2191
我寻月下人不归
我寻月下人不归 2020-12-07 23:01

I\'m trying to deploy a windows service but not quite sure how to do it right. I built it as a console app to start with, I\'ve now turned it into a windows service project

8条回答
  •  星月不相逢
    2020-12-07 23:30

    This is a base service class (ServiceBase subclass) that can be subclassed to build a windows service that can be easily installed from the command line, without installutil.exe. This solution is derived from How to make a .NET Windows Service start right after the installation?, adding some code to get the service Type using the calling StackFrame

    public abstract class InstallableServiceBase:ServiceBase
    {
    
        /// 
        /// returns Type of the calling service (subclass of InstallableServiceBase)
        /// 
        /// 
        protected static Type getMyType()
        {
            Type t = typeof(InstallableServiceBase);
            MethodBase ret = MethodBase.GetCurrentMethod();
            Type retType = null;
            try
            {
                StackFrame[] frames = new StackTrace().GetFrames();
                foreach (StackFrame x in frames)
                {
                    ret = x.GetMethod();
    
                    Type t1 = ret.DeclaringType;
    
                    if (t1 != null && !t1.Equals(t) &&   !t1.IsSubclassOf(t))
                    {
    
    
                        break;
                    }
                    retType = t1;
                }
            }
            catch
            {
    
            }
            return retType;
        }
        /// 
        /// returns AssemblyInstaller for the calling service (subclass of InstallableServiceBase)
        /// 
        /// 
        protected static AssemblyInstaller GetInstaller()
        {
            Type t = getMyType();
            AssemblyInstaller installer = new AssemblyInstaller(
                t.Assembly, null);
            installer.UseNewContext = true;
            return installer;
        }
    
        private bool IsInstalled()
        {
            using (ServiceController controller =
                new ServiceController(this.ServiceName))
            {
                try
                {
                    ServiceControllerStatus status = controller.Status;
                }
                catch
                {
                    return false;
                }
                return true;
            }
        }
    
        private bool IsRunning()
        {
            using (ServiceController controller =
                new ServiceController(this.ServiceName))
            {
                if (!this.IsInstalled()) return false;
                return (controller.Status == ServiceControllerStatus.Running);
            }
        }
        /// 
        /// protected method to be called by a public method within the real service
        /// ie: in the real service
        ///    new internal  void InstallService()
        ///    {
        ///        base.InstallService();
        ///    }
        /// 
        protected void InstallService()
        {
            if (this.IsInstalled()) return;
    
            try
            {
                using (AssemblyInstaller installer = GetInstaller())
                {
    
                    IDictionary state = new Hashtable();
                    try
                    {
                        installer.Install(state);
                        installer.Commit(state);
                    }
                    catch
                    {
                        try
                        {
                            installer.Rollback(state);
                        }
                        catch { }
                        throw;
                    }
                }
            }
            catch
            {
                throw;
            }
        }
        /// 
        /// protected method to be called by a public method within the real service
        /// ie: in the real service
        ///    new internal  void UninstallService()
        ///    {
        ///        base.UninstallService();
        ///    }
        /// 
        protected void UninstallService()
        {
            if (!this.IsInstalled()) return;
    
            if (this.IsRunning()) {
                this.StopService();
            }
            try
            {
                using (AssemblyInstaller installer = GetInstaller())
                {
                    IDictionary state = new Hashtable();
                    try
                    {
                        installer.Uninstall(state);
                    }
                    catch
                    {
                        throw;
                    }
                }
            }
            catch
            {
                throw;
            }
        }
    
        private void StartService()
        {
            if (!this.IsInstalled()) return;
    
            using (ServiceController controller =
                new ServiceController(this.ServiceName))
            {
                try
                {
                    if (controller.Status != ServiceControllerStatus.Running)
                    {
                        controller.Start();
                        controller.WaitForStatus(ServiceControllerStatus.Running,
                            TimeSpan.FromSeconds(10));
                    }
                }
                catch
                {
                    throw;
                }
            }
        }
    
        private void StopService()
        {
            if (!this.IsInstalled()) return;
            using (ServiceController controller =
                new ServiceController(this.ServiceName))
            {
                try
                {
                    if (controller.Status != ServiceControllerStatus.Stopped)
                    {
                        controller.Stop();
                        controller.WaitForStatus(ServiceControllerStatus.Stopped,
                             TimeSpan.FromSeconds(10));
                    }
                }
                catch
                {
                    throw;
                }
            }
        }
    }
    

    All you have to do is to implement two public/internal methods in your real service:

        new internal  void InstallService()
        {
            base.InstallService();
        }
        new internal void UninstallService()
        {
            base.UninstallService();
        }
    

    and then call them when you want to install the service:

        static void Main(string[] args)
        {
            if (Environment.UserInteractive)
            {
                MyService s1 = new MyService();
                if (args.Length == 1)
                {
                    switch (args[0])
                    {
                        case "-install":
                            s1.InstallService();
    
                            break;
                        case "-uninstall":
    
                            s1.UninstallService();
                            break;
                        default:
                            throw new NotImplementedException();
                    }
                }
    
    
            }
            else {
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[] 
                { 
                    new MyService() 
                };
                ServiceBase.Run(MyService);            
            }
    
        }
    

提交回复
热议问题