2010-05-18 4 views
31

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

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

Я посмотрел на предыдущий вопрос, Install a .NET windows service without InstallUtil.exe, но я просто хочу убедиться, что правильно понял.

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

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

+0

дубликат - http://stackoverflow.com/questions/255056/install-a-net-windows-service-without-installutil-exe –

+0

@AZ Да, я знаю, я подумал, что все равно будет задавать вопрос, поскольку я имею в виду предыдущий вопрос, а мой немного отличается тем, что он не является сервисом .net (у него нет интерфейса), поэтому хотел бы убедиться, что те же ответы будут применяться. – annelie

ответ

17

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

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

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

+0

Спасибо, я почти с этим. Я получаю исключение безопасности: «Источник не найден, но некоторые или все журналы событий не могут быть найдены. Недостижимые журналы: безопасность.Я предполагаю, что это может иметь отношение к учетной записи, в которой он работает, поскольку @ho говорит в своем комментарии. Я установил его в LocalService, но я изменю его и повторю попытку. Кстати, крошечная орфографическая ошибка в вашем коде, для InstallService() он говорит: «IDictionary state = new Hasttable();» а не Hashtable. – annelie

+0

Исправлено. Благодарю. –

+0

Нет проблем. Правильно, я пробовал со всеми разными учетными записями, за исключением того, что Пользователь дает то же исключение, а для пользователя я должен ввести имя пользователя и пароль. Какое имя пользователя и пароль должны быть? Для пользователя я вхожу на сервер с помощью? – annelie

0

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

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

5

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

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

Voila, и все готово.

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

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

+0

Спасибо, я посмотрю на это, если не могу заставить другие предложения работать. Не знаете, какие полномочия вы имеете в виду? – annelie

+0

С учетными данными он означает учетную запись, на которую работает служба. –

+0

@ho Какую учетную запись следует запускать под? В основном служба просматривает некоторые папки для новых файлов, загружает файлы в базу данных, если есть новые файлы, а затем перемещает файлы в другую папку. – annelie

28

Вы можете использовать InstallUtil без визуальной студии, он входит с.чистая основа

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

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) 
30

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

Вы можете установить услугу с помощью команды: 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

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

+2

Это очень просто и должно быть выше, чем другие методы. – Sam

+3

Я думаю, что это самый простой способ установить службу Windows – ykh

+1

Я согласен, это самое простое решение и должно быть одобрено FAR больше, чем другие решения UBER COMPLEX! Хорошая вещь! –

0

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

http://topshelf-project.com/

0

Эта проблема обусловлена ​​безопасность, лучше с открытым Разработчиком Командной строки для VS 2012 в режиме администратора и установить службу, это исправить вашу проблему, конечно.

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

    } 
Смежные вопросы