不使用InstallUtil.exe安装Windows服务

时间:2010-05-18 11:22:24

标签: c# deployment windows-services install

我正在尝试部署Windows服务,但不太确定如何正确执行。我将它构建为一个控制台应用程序,我现在把它变成一个Windows服务项目,然后从服务中的OnStart方法调用我的类。

我现在需要在没有Visual Studio的服务器上安装它,如果我正确理解它意味着我不能使用InstallUtil.exe而必须创建一个安装程序类。这是对的吗?

我确实看过上一个问题,Install a .NET windows service without InstallUtil.exe,但我只是想确保我已正确理解。

如果我创建了问题已接受答案链接的课程,下一步是什么?将MyService.exe和MyService.exe.config上传到服务器,双击exe文件,Bob是我的叔叔?

该服务只会安装在一台服务器上。

8 个答案:

答案 0 :(得分:44)

我知道这是一个非常古老的问题,但最好用新信息更新它。

您可以使用sc命令安装服务:

<强> InstallService.bat:

@echo OFF
echo Stopping old service version...
net stop "[YOUR SERVICE NAME]"
echo Uninstalling old service version...
sc delete "[YOUR SERVICE NAME]"

echo Installing service...
rem DO NOT remove the space after "binpath="!
sc create "[YOUR SERVICE NAME]" binpath= "[PATH_TO_YOUR_SERVICE_EXE]" start= auto
echo Starting server complete
pause

使用SC,您还可以执行更多操作:卸载旧服务(如果您之前已经安装过),检查是否存在具有相同名称的服务...甚至将您的服务设置为自动启动。

许多参考文献之一:creating a service with sc.exe; how to pass in context parameters

我已经通过这种方式和&amp; InstallUtil。就个人而言,我觉得使用SC更清洁,更健康。

答案 1 :(得分:31)

你仍然可以在没有visual studio的情况下使用installutil,它包含在.net框架

在服务器上,以管理员身份打开命令提示符:

CD C:\Windows\Microsoft.NET\Framework\v4.0.version (insert your version)

installutil "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location)

要卸载:

installutil /u "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location)

答案 2 :(得分:18)

InstallUtil.exe工具只是针对服务中安装程序组件的一些反射调用的包装器。因此,它实际上没有做太多,但运用这些安装程序组件提供的功能。 Marc Gravell的解决方案只是提供了一种从命令行执行此操作的方法,这样您就不必再依赖于目标计算机上的InstallUtil.exe

以下是基于Marc Gravell解决方案的逐步步骤。

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

答案 3 :(得分:5)

为什么不创建一个安装项目?这真的很容易。

  1. 向服务添加服务安装程序(您在看似无用的服务“设计”表面上执行此操作)
  2. 创建安装项目并将服务输出添加到安装应用程序文件夹
  3. 最重要的是将服务项目输出添加到所有自定义操作
  4. 瞧,你已经完成了。

    请点击此处了解更多信息: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx

    还有一种方法可以提示用户提供凭据(或提供自己的凭据)。

答案 4 :(得分:2)

这是一个基本服务类(ServiceBase子类),可以进行子类化以构建可以从命令行轻松安装的Windows服务,而无需installutil.exe。此解决方案派生自How to make a .NET Windows Service start right after the installation?,添加了一些代码以使用调用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;
            }
        }
    }
}

您所要做的就是在实际服务中实现两种公共/内部方法:

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

然后在您要安装服务时调用它们:

    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);            
        }

    }

答案 5 :(得分:0)

不是双击,而是使用正确的命令行参数运行它,因此键入类似MyService -i然后MyService -u的内容来卸载它。

您可以使用sc.exe安装和卸载它(或沿InstallUtil.exe复制)。

答案 6 :(得分:0)

Topshelf是一个OSS项目,在这个问题得到解答后启动,它使Windows服务变得更加容易。我强烈建议您查看它。

http://topshelf-project.com/

答案 7 :(得分:0)

此问题是由于安全性,在RUN AS ADMINISTRATOR中更好地打开VS 2012的开发人员命令提示并安装您的服务,它确实可以解决您的问题。