Как сделать так, чтобы.NET Windows Service запускался сразу после установки?
Помимо service.StartType = ServiceStartMode.Automatic мой сервис не запускается после установки
Решение
Вставил этот код в мой ProjectInstaller
protected override void OnAfterInstall(System.Collections.IDictionary savedState)
{
base.OnAfterInstall(savedState);
using (var serviceController = new ServiceController(this.serviceInstaller1.ServiceName, Environment.MachineName))
serviceController.Start();
}
Спасибо Скотту и Фрэнсису Б.
8 ответов
Вы можете сделать все это из исполняемого файла службы в ответ на события, инициированные процессом InstallUtil. Переопределите событие OnAfterInstall, чтобы использовать класс ServiceController для запуска службы.
http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstaller.aspx
Я разместил пошаговую процедуру для создания службы Windows в C# здесь. Похоже, вы хотя бы до этого момента, и теперь вы задаетесь вопросом, как запустить службу после ее установки. Если для свойства StartType установлено значение "Автоматически", служба будет автоматически запускаться после перезагрузки системы, но не будет (как вы обнаружили) автоматически запускать службу после установки.
Я не помню, где я нашел его изначально (возможно, Марк Грэвелл?), Но я нашел решение в Интернете, которое позволяет вам устанавливать и запускать свой сервис, фактически запуская сам сервис. Вот пошаговая инструкция:
Структурировать
Main()
функция вашего сервиса, как это:static void Main(string[] args) { if (args.Length == 0) { // Run your service normally. ServiceBase[] ServicesToRun = new ServiceBase[] {new YourService()}; ServiceBase.Run(ServicesToRun); } else if (args.Length == 1) { switch (args[0]) { case "-install": InstallService(); StartService(); break; case "-uninstall": StopService(); UninstallService(); break; default: throw new NotImplementedException(); } } }
Вот вспомогательный код:
using System.Collections; using System.Configuration.Install; using System.ServiceProcess; private static bool IsInstalled() { using (ServiceController controller = new ServiceController("YourServiceName")) { try { ServiceControllerStatus status = controller.Status; } catch { return false; } return true; } } private static bool IsRunning() { using (ServiceController controller = new ServiceController("YourServiceName")) { if (!IsInstalled()) return false; return (controller.Status == ServiceControllerStatus.Running); } } private static AssemblyInstaller GetInstaller() { AssemblyInstaller installer = new AssemblyInstaller( typeof(YourServiceType).Assembly, null); installer.UseNewContext = true; return installer; }
Продолжая с кодом поддержки...
private static void InstallService() { if (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; } } private static void UninstallService() { if ( !IsInstalled() ) return; try { using ( AssemblyInstaller installer = GetInstaller() ) { IDictionary state = new Hashtable(); try { installer.Uninstall( state ); } catch { throw; } } } catch { throw; } } private static void StartService() { if ( !IsInstalled() ) return; using (ServiceController controller = new ServiceController("YourServiceName")) { try { if ( controller.Status != ServiceControllerStatus.Running ) { controller.Start(); controller.WaitForStatus( ServiceControllerStatus.Running, TimeSpan.FromSeconds( 10 ) ); } } catch { throw; } } } private static void StopService() { if ( !IsInstalled() ) return; using ( ServiceController controller = new ServiceController("YourServiceName")) { try { if ( controller.Status != ServiceControllerStatus.Stopped ) { controller.Stop(); controller.WaitForStatus( ServiceControllerStatus.Stopped, TimeSpan.FromSeconds( 10 ) ); } } catch { throw; } } }
На этом этапе, после установки службы на целевом компьютере, просто запустите службу из командной строки (как любое обычное приложение) с
-install
Аргумент командной строки для установки и запуска вашего сервиса.
Я думаю, что я охватил все, но если вы обнаружите, что это не работает, пожалуйста, дайте мне знать, чтобы я мог обновить ответ.
Visual Studio
Если вы создаете проект установки с VS, вы можете создать настраиваемое действие, которое вызвало метод.NET для запуска службы. Но на самом деле не рекомендуется использовать управляемые пользовательские действия в MSI. Смотрите эту страницу.
ServiceController controller = new ServiceController();
controller.MachineName = "";//The machine where the service is installed;
controller.ServiceName = "";//The name of your service installed in Windows Services;
controller.Start();
InstallShield или Wise
Если вы используете InstallShield или Wise, эти приложения предоставляют возможность запуска службы. В соответствии с примером с Wise, вы должны добавить действие управления службой. В этом действии вы указываете, хотите ли вы запускать или останавливать службу.
Wix
Используя Wix, вам нужно добавить следующий xml-код в компонент вашего сервиса. Для получения дополнительной информации об этом, вы можете проверить эту страницу.
<ServiceInstall
Id="ServiceInstaller"
Type="ownProcess"
Vital="yes"
Name=""
DisplayName=""
Description=""
Start="auto"
Account="LocalSystem"
ErrorControl="ignore"
Interactive="no">
<ServiceDependency Id="????"/> ///Add any dependancy to your service
</ServiceInstall>
Вам нужно добавить пользовательское действие в конец последовательности "ExecuteImmediate" в MSI, используя имя компонента EXE или пакет (sc start) в качестве источника. Я не думаю, что это может быть сделано с Visual Studio, вам, возможно, придется использовать настоящий инструмент MSI для этого.
Используйте класс.NET ServiceController, чтобы запустить его, или введите команду командной строки, чтобы запустить его - "net start servicename". В любом случае работает.
Чтобы добавить ответ ScottTx, вот фактический код для запуска службы, если вы делаете это способом Microsoft (то есть, используя проект установки и т. Д.)
(извините за код VB.net, но это то, что я застрял)
Private Sub ServiceInstaller1_AfterInstall(ByVal sender As System.Object, ByVal e As System.Configuration.Install.InstallEventArgs) Handles ServiceInstaller1.AfterInstall
Dim sc As New ServiceController()
sc.ServiceName = ServiceInstaller1.ServiceName
If sc.Status = ServiceControllerStatus.Stopped Then
Try
' Start the service, and wait until its status is "Running".
sc.Start()
sc.WaitForStatus(ServiceControllerStatus.Running)
' TODO: log status of service here: sc.Status
Catch ex As Exception
' TODO: log an error here: "Could not start service: ex.Message"
Throw
End Try
End If
End Sub
Чтобы создать описанный выше обработчик событий, перейдите в конструктор ProjectInstaller, где находятся 2 элемента управления. Нажмите на элемент управления ServiceInstaller1. Перейдите в окно свойств под событиями, и там вы найдете событие AfterInstall.
Примечание. Не помещайте указанный выше код в событие AfterInstall для ServiceProcessInstaller1. Это не сработает, исходя из опыта.:)
Чтобы запустить его сразу после установки, я создаю командный файл с installutil, а затем sc start
Это не идеально, но работает....
Самое простое решение здесь можно найти: /questions/1590753/ustanovka-sluzhbyi-windows-bez-installutilexe от @Hoàng Long
@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