简体   繁体   English

不使用InstallUtil.exe安装Windows服务

[英]Install windows service without InstallUtil.exe

I'm trying to deploy a windows service but not quite sure how to do it right. 我正在尝试部署Windows服务但不太确定如何正确执行。 I built it as a console app to start with, I've now turned it into a windows service project and just call my class from the OnStart method in the service. 我将它构建为控制台应用程序,我现在将其转换为Windows服务项目,并从服务中的OnStart方法调用我的类。

I now need to install this on a server which doesn't have Visual Studio on it, which if I've understood it correctly means I can't use the InstallUtil.exe and have to create an installer class instead. 我现在需要在没有Visual Studio的服务器上安装它,如果我正确理解它意味着我不能使用InstallUtil.exe而必须创建一个安装程序类。 Is this correct? 它是否正确?

I did have a look at a previous question, Install a .NET windows service without InstallUtil.exe , but I just want to make sure I've understood it correctly. 我确实看过上一个问题, 安装没有InstallUtil.exe的.NET Windows服务 ,但我只是想确保我已经正确理解它。

If I create the class that question's accepted answer links to, what is the next step? 如果我创建了问题的接受答案链接到的类,下一步是什么? Upload MyService.exe and MyService.exe.config to the server, double click the exe file and Bob's my uncle? 将MyService.exe和MyService.exe.config上传到服务器,双击exe文件,Bob是我的叔叔?

The service will only ever be installed on one server. 该服务只能安装在一台服务器上。

I know it is a very old question, but better update it with new information. 我知道这是一个非常古老的问题,但最好用新信息更新它。

You can install service by using sc command: 您可以使用sc命令安装服务:

InstallService.bat: 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

With SC, you can do a lot more things as well: uninstalling the old service (if you already installed it before), checking if service with same name exists... even set your service to autostart. 使用SC,您还可以执行更多操作:卸载旧服务(如果您之前已经安装过),检查是否存在具有相同名称的服务...甚至将您的服务设置为自动启动。

One of many references: creating a service with sc.exe; 许多参考资料之一: 使用sc.exe创建服务; how to pass in context parameters 如何传入上下文参数

I have done by both this way & InstallUtil . 我已经通过这种方式和InstallUtil完成了。 Personally I feel that using SC is cleaner and better for your health. 就个人而言,我觉得使用SC更清洁,更健康。

You can still use installutil without visual studio, it is included with the .net framework 您仍然可以在没有visual studio的情况下使用installutil,它包含在.net框架中

On your server, open a command prompt as administrator then: 在服务器上,以管理员身份打开命令提示符:

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

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

To uninstall: 要卸载:

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

The InstallUtil.exe tool is simply a wrapper around some reflection calls against the installer component(s) in your service. InstallUtil.exe工具只是针对服务中的安装程序组件的一些反射调用的包装器。 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. Marc Gravell的解决方案只是提供了一种从命令行执行此操作的方法,因此您不再需要依赖目标计算机上的InstallUtil.exe

Here's my step-by-step that based on Marc Gravell's solution. 这是我基于Marc Gravell解决方案的一步一步。

How to make a .NET Windows Service start right after the installation? 如何在安装后立即启动.NET Windows服务?

Why not just create a setup project? 为什么不创建一个安装项目? It's really easy. 这真的很容易。

  1. Add a service installer to the service (you do it on the seemingly useless service "design" surface) 将服务安装程序添加到服务中(您在看似无用的服务“设计”表面上执行此操作)
  2. Create a setup project and add the Service output to the setup app folder 创建安装项目并将服务输出添加到安装应用程序文件夹
  3. Most importantly add the Service project output to all the custom actions 最重要的是将Service项目输出添加到所有自定义操作

Voila, and you're done. 瞧,你已经完成了。

See here for more: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx 有关更多信息,请参见此处: http//www.codeproject.com/KB/dotnet/simplewindowsservice.aspx

There is also a way to prompt the user for credentials (or supply your own). 还有一种方法可以提示用户输入凭据(或提供自己的凭据)。

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. 这是一个基本服务类(ServiceBase子类),可以进行子类化以构建可以从命令行轻松安装的Windows服务,而无需installutil.exe。 This solution is derived from How to make a .NET Windows Service start right after the installation? 此解决方案源自如何在安装后立即启动.NET Windows服务? , adding some code to get the service Type using the calling StackFrame ,添加一些代码以使用调用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);            
        }

    }

Topshelf is an OSS project which was started after this question was answered and it makes Windows service much, MUCH easier.I highly recommend looking into it. Topshelf是一个OSS项目,在这个问题得到解答后启动,它使Windows服务变得更加容易。我强烈建议您进行调查。

http://topshelf-project.com/ http://topshelf-project.com/

Not double click, you run it with the correct command line parameters, so type something like MyService -i and then MyService -u to uninstall it`. 不是双击,你使用正确的命令行参数运行它,所以键入类似MyService -i然后MyService -u来卸载它。

You could otherwise use sc.exe to install and uninstall it (or copy along InstallUtil.exe). 否则,您可以使用sc.exe来安装和卸载它(或沿InstallUtil.exe复制)。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在没有InstallUtil.exe的情况下安装.NET Windows服务 - Install a .NET windows service without InstallUtil.exe 在安装期间使用 InstallUtil.exe 命令安装 windows 服务 - Install a windows service with InstallUtil.exe command during an installation 使用InstallUtil.exe并设置Windows服务密码包含空格 - Using InstallUtil.exe and Setting Windows Service Password Containing Spaces 通过“无法启动服务……必须首先安装Windows服务(使用installutil.exe)……”的性能和诊断。 - Performance and diagnostics with “Cannot start service… A Windows Service must first be intalled (using installutil.exe)…” System.BadImageFormatException:尝试使用installutil.exe安装服务时无法加载文件或程序集...格式不正确 - System.BadImageFormatException:Could not load file or assembly … incorrect format when trying to install service with installutil.exe c# Windows 使用 installutil.exe 发布时服务不起作用 - c# Windows Service does not work when publish with installutil.exe 使用 InstallUtil 命令安装 Windows 服务失败 - Install Windows service failing with InstallUtil command 无法在InstallUtil工具的帮助下安装Windows服务 - Unable to install windows service with the help of InstallUtil tool 为什么 InstallUtil.exe 找不到清单文件? - Why can't InstallUtil.exe find the manifest file? 使用InstallUtil安装具有启动参数的Windows服务 - Using InstallUtil to install a Windows service with startup parameters
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM