Установите Windows-сервис без InstallUtil.exe

Я пытаюсь развернуть службу Windows, но не совсем уверен, как это сделать правильно. Я создал его в качестве консольного приложения для начала, теперь я превратил его в проект службы Windows и просто вызываю свой класс из метода OnStart в службе.

Теперь мне нужно установить это на сервер, на котором нет Visual Studio, который, если я правильно понял, означает, что я не могу использовать InstallUtil.exe и вместо этого должен создать класс установщика. Правильно ли это?

Я просмотрел предыдущий вопрос Установить службу Windows.NET без InstallUtil.exe, но я просто хочу убедиться, что понял правильно.

Если я создаю класс, на который были приняты ответы на ответные ссылки, каков следующий шаг? Загрузите MyService.exe и MyService.exe.config на сервер, дважды щелкните файл exe и Боб мой дядя?

Служба будет установлена ​​только на одном сервере.

Ответ 1

Инструмент InstallUtil.exe - это просто обертка вокруг вызовов отражения от компонентов (-ов) установщика в вашей службе. Таким образом, на самом деле это не делает ничего, кроме использования функций, предоставляемых этими компонентами установщика. Решение Marc Gravell просто предоставляет средства для этого из командной строки, так что вам больше не нужно полагаться на InstallUtil.exe на целевой машине.

Здесь мой шаг за шагом, основанный на решении Марка Гравелла.

Как запустить службу .NET Windows сразу после установки?

Ответ 2

Вы все еще можете использовать 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)

Ответ 3

Я знаю, что это очень старый вопрос, но лучше обновить его с помощью новой информации.

Вы можете установить сервис, используя команду 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 вы можете сделать гораздо больше: удаление старой службы (если вы уже установили ее раньше), проверьте, существует ли служба с тем же именем... даже настройте службу автозапуска.

Одна из многих ссылок: создание сервиса с помощью sc.exe; как передать параметры контекста

Я сделал так и InstallUtil. Лично я чувствую, что использование SC чище и лучше для вашего здоровья.

Ответ 4

Почему бы просто не создать проект установки? Это очень легко.

  • Добавить службу установки в службу (вы делаете это на поверхности кажущейся бесполезной службы "дизайн" )
  • Создайте проект установки и добавьте вывод службы в папку приложения настройки
  • Самое главное добавить вывод Сервисного проекта ко всем пользовательским действиям

Воила, и все готово.

Смотрите здесь: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx

Существует также способ запросить у пользователя учетные данные (или предоставить свои собственные).

Ответ 5

Это базовый класс сервиса (подкласс ServiceBase), который может быть подклассифицирован для создания службы Windows, которую можно легко установить из командной строки без installutil.exe. Это решение получено из Как запустить службу Windows Windows сразу после установки?, добавив некоторый код для получения типа сервиса с помощью вызывающего 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);            
        }

    }

Ответ 6

Не дважды щелкните, вы запустите его с правильными параметрами командной строки, поэтому введите что-то вроде MyService -i, а затем MyService -u, чтобы удалить его.

В противном случае вы можете использовать sc.exe для его установки и удаления (или скопировать по InstallUtil.exe).

Ответ 7

Topshelf - это проект OSS, который был запущен после ответа на этот вопрос, и он делает службу Windows намного проще. Я очень рекомендую глядя в нее.

http://topshelf-project.com/

Ответ 8

Эта проблема возникает из-за безопасности, лучше откройте командную строку разработчика для VS 2012 в RUN AS ADMINISTRATOR и установите свою службу, она исправит вашу проблему.