วิธีการทำให้. NET Windows Service เริ่มต้นทันทีหลังการติดตั้ง?


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 ให้ใช้โซลูชันบรรทัดคำสั่ง
Matt Davis

182

ผมเคยโพสต์ขั้นตอนขั้นตอนโดยขั้นตอนในการสร้างบริการของ Windows ใน C # ที่นี่ ดูเหมือนว่าคุณจะมาถึงจุดนี้เป็นอย่างน้อยและตอนนี้คุณกำลังสงสัยว่าจะเริ่มบริการได้อย่างไรเมื่อติดตั้งแล้ว การตั้งค่าคุณสมบัติ StartType เป็น Automatic จะทำให้บริการเริ่มทำงานโดยอัตโนมัติหลังจากรีบูตระบบของคุณ แต่จะไม่ (ตามที่คุณค้นพบ) เริ่มบริการของคุณโดยอัตโนมัติหลังการติดตั้ง

ฉันจำไม่ได้ว่าพบที่ไหนในตอนแรก (อาจจะเป็น Marc Gravell?) แต่ฉันพบวิธีแก้ปัญหาออนไลน์ที่ช่วยให้คุณสามารถติดตั้งและเริ่มบริการได้โดยเรียกใช้บริการของคุณเอง นี่คือขั้นตอนโดยขั้นตอน:

  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อาร์กิวเมนต์บรรทัดคำสั่งเพื่อติดตั้งและเริ่มบริการของคุณ

ฉันคิดว่าฉันครอบคลุมทุกอย่างแล้ว แต่หากคุณพบว่าสิ่งนี้ไม่ได้ผลโปรดแจ้งให้เราทราบเพื่อให้ฉันได้อัปเดตคำตอบ


13
โปรดทราบว่าโซลูชันนี้ไม่จำเป็นต้องใช้ InstallUtil.exe ดังนั้นคุณไม่จำเป็นต้องส่งมอบเป็นส่วนหนึ่งของโปรแกรมการติดตั้งของคุณ
Matt Davis

3
จุดที่มีประโยค "catch {throw;}" ว่างคืออะไร นอกจากนี้อาจไม่ใช่ความคิดที่ดีที่จะซ่อนความล้มเหลวโดย "Rollback ()" เนื่องจากสถานการณ์นั้นทำให้ระบบอยู่ในสถานะที่ไม่ได้กำหนดฉันเดาว่า (คุณพยายามติดตั้งบริการล้มเหลวตรงกลางและไม่สามารถยกเลิกได้ ). อย่างน้อยคุณควร "แสดง" ให้ผู้ใช้เห็นว่ามีอะไรคาว - หรือฟังก์ชัน Rollback () เขียนข้อความบางอย่างลงในคอนโซลหรือไม่?
Christian.K

5
การย้อนกลับจะเขียนข้อมูลไปยังคอนโซล สำหรับบล็อก Catch ที่ว่างเปล่ามันเป็นสิ่งที่ดีบัก ฉันสามารถวางเบรกพอยต์ไว้ที่คำสั่ง throw เพื่อตรวจสอบข้อยกเว้นที่อาจเกิดขึ้น
Matt Davis

4
ฉันได้รับข้อผิดพลาด Error: ไม่พบชนิดหรือชื่อเนมสเปซ 'YourServiceType' (คุณไม่มีคำสั่งการใช้งานหรือการอ้างอิงการประกอบหรือไม่
Yogesh

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

คุณต้องเพิ่ม Custom Action ต่อท้ายลำดับ 'ExecuteImmediate' ใน MSI โดยใช้ชื่อส่วนประกอบของ EXE หรือ batch (sc start) เป็นแหล่งที่มา ฉันไม่คิดว่าจะสามารถทำได้ด้วย Visual Studio คุณอาจต้องใช้เครื่องมือสร้าง MSI จริงสำหรับสิ่งนั้น


4

ในการเริ่มต้นทันทีหลังการติดตั้งฉันสร้างไฟล์แบตช์พร้อม installutil ตามด้วย sc start

ไม่เหมาะ แต่ได้ผล ....


4

ใช้คลาส. NET ServiceController เพื่อเริ่มต้นหรือออกคำสั่ง commandline เพื่อเริ่มต้น --- "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

ขอบคุณข้อมูลนี้ช่วยให้ฉันทราบวิธีเริ่มบริการโดยอัตโนมัติ
Charles Owen

0

วิธีแก้ปัญหาที่ง่ายที่สุดอยู่ที่นี่install-windows-service-without-installutil-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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.