Install windows service without InstallUtil.exe

前端 未结 8 2182
我寻月下人不归
我寻月下人不归 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:24

    The InstallUtil.exe tool is simply a wrapper around some reflection calls against the installer component(s) in your service. As such, it really doesn't do much but exercise the functionality these installer components provide. Marc Gravell's solution simply provides a means to do this from the command line so that you no longer have to rely on having InstallUtil.exe on the target machine.

    Here's my step-by-step that based on Marc Gravell's solution.

    How to make a .NET Windows Service start right after the installation?

    0 讨论(0)
  • 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
    {
    
        /// <summary>
        /// returns Type of the calling service (subclass of InstallableServiceBase)
        /// </summary>
        /// <returns></returns>
        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;
        }
        /// <summary>
        /// returns AssemblyInstaller for the calling service (subclass of InstallableServiceBase)
        /// </summary>
        /// <returns></returns>
        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);
            }
        }
        /// <summary>
        /// protected method to be called by a public method within the real service
        /// ie: in the real service
        ///    new internal  void InstallService()
        ///    {
        ///        base.InstallService();
        ///    }
        /// </summary>
        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;
            }
        }
        /// <summary>
        /// protected method to be called by a public method within the real service
        /// ie: in the real service
        ///    new internal  void UninstallService()
        ///    {
        ///        base.UninstallService();
        ///    }
        /// </summary>
        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);            
            }
    
        }
    
    0 讨论(0)
提交回复
热议问题