Установка службы Windows без InstallUtil.exe - PullRequest
37 голосов
/ 18 мая 2010

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

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

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

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

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

Ответы [ 8 ]

46 голосов
/ 11 декабря 2015

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

Службу можно установить с помощью команды 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; как передать в контекст параметры

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

31 голосов
/ 08 мая 2014

Вы все еще можете использовать installutil без visual studio, он включен в .net framework

На вашем сервере откройте командную строку от имени администратора, затем:

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)
18 голосов
/ 18 мая 2010

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

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

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

5 голосов
/ 18 мая 2010

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

  1. Добавление установщика службы в службу (вы делаете это на кажущейся бесполезной «дизайнерской» поверхности службы)
  2. Создание проекта установки и добавление вывода службы в папку приложения установки
  3. Наиболее важно добавить выходные данные проекта службы ко всем настраиваемым действиям

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

Смотрите здесь для получения дополнительной информации: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx

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

2 голосов
/ 11 июля 2016

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

    }
0 голосов
/ 29 апреля 2016

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

0 голосов
/ 28 января 2016

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

http://topshelf -project.com /

0 голосов
/ 18 мая 2010

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

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

...