Як змусити службу Windows .NET Windows запустити відразу після встановлення?


88

Окрім service.StartType = ServiceStartMode. Автоматично моя служба не запускається після встановлення

Рішення

Вставив цей код у мій ProjectInstaller

protected override void OnAfterInstall(System.Collections.IDictionary savedState)
{
    base.OnAfterInstall(savedState);
    using (var serviceController = new ServiceController(this.serviceInstaller1.ServiceName, Environment.MachineName))
        serviceController.Start();
}

Завдяки ScottTx та Francis B.


Він не запускається відразу після встановлення або не запускається під час перезавантаження?
Chris Van Opstal

Відповіді:


21

Ви можете зробити все це у своєму виконуваному файлі служби у відповідь на події, запущені в процесі InstallUtil. Перевизначте подію OnAfterInstall, щоб використовувати клас ServiceController для запуску служби.

http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstaller.aspx


3
Це приємне рішення, але все ж вимагає використання утиліти InstallUtil. Якщо ви вже постачаєте InstallUtil як частину інсталяції, це має найбільший сенс. Але якщо ви хочете відмовитися від упаковки InstallUtil, скористайтеся рішенням командного рядка.
Метт Девіс,

181

Я відправив процедуру крок за кроком для створення служби Windows в C # тут . Схоже, ви принаймні до цього моменту, і тепер ви задаєтесь питанням, як запустити службу після її встановлення. Якщо встановити для властивості StartType значення Автоматично, служба перезапуститься автоматично після перезавантаження вашої системи, але після встановлення вона не запуститься автоматично (як ви виявили).

Я не пам’ятаю, де я його знайшов спочатку (можливо, Марк Гравелл?), Але в мережі я знайшов рішення, яке дозволяє встановити та запустити службу, фактично запустивши її. Ось крок за кроком:

  1. Структуруйте 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();
            }
        }
    }
    
  2. Ось допоміжний код:

    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;
    }
    
  3. Продовжуючи підтримуючий код ...

    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;
            }
        }
    }
    
  4. На цьому етапі, після встановлення вашої служби на цільовій машині, просто запустіть службу з командного рядка (як будь-яка звичайна програма) з -installаргументом командного рядка, щоб встановити та запустити службу.

Я думаю, що я все висвітлив, але якщо ви виявите, що це не працює, будь ласка, повідомте мене, щоб я міг оновити відповідь.


12
Зверніть увагу, що це рішення не вимагає використання InstallUtil.exe, тому вам не доведеться доставляти його як частину інсталяційної програми.
Matt Davis

3
Який сенс у порожніх реченнях "catch {throw;}"? Крім того, мабуть, це не гарна ідея приховувати помилки методом "Відкат ()", оскільки ця ситуація, в основному, залишає систему у невизначеному стані, я думаю (ви намагалися встановити службу, не вдалося десь посередині і не змогли її скасувати ). Ви повинні принаймні "показати" користувачеві, що там щось непотрібне - чи функція Rollback () пише деякі повідомлення на консоль?
Крістіан.

5
Відкат робить запис даних на консоль. Що стосується порожніх блоків catch, то це налагодження. Я можу поставити точку зупинки в операторі throw, щоб вивчити будь-які винятки, які можуть виникнути.
Метт Девіс,

4
Я отримую помилку Помилка: Не вдалося знайти ім’я типу або простору імен „YourServiceType” (вам не вистачає директиви або посилання на збірку?
Йогеш,

5
YourServiceTypeце те, що ProjectInstallerви додали до служби, яка містить ServiceInstallerіServiceProcessInstaller
bansi

6

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>

5

Вам потрібно додати Спеціальну дію в кінець послідовності 'ExecuteImmediate' у MSI, використовуючи в якості джерела ім'я компонента EXE або партію (sc start). Я не думаю, що цього можна зробити за допомогою Visual Studio, можливо, вам доведеться використовувати для цього справжній інструмент розробки MSI.


4

Щоб запустити його відразу після інсталяції, я створюю пакетний файл за допомогою installlutil з подальшим запуском sc

Це не ідеально, але працює ....


4

Використовуйте клас .NET ServiceController, щоб запустити його, або виконайте команду командного рядка, щоб запустити --- "net start servicename". У будь-якому випадку це працює.


4

Щоб додати до відповіді 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. Це не буде працювати, виходячи з досвіду. :)


Код VB.net непоганий! Тим з нас, хто працює кількома мовами, приємно не перетворювати код із мови C!
Steve Reed Sr

Дякую, це допомогло мені зрозуміти, як автоматично запускати послугу.
Чарльз Оуен,

0

Найпростіше рішення можна знайти тут install-windows-service-without-installlutil-exe від @ 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.