Làm cách nào để khởi động Dịch vụ Windows .NET ngay sau khi cài đặt?


88

Bên cạnh dịch vụ.StartType = ServiceStartMode. Tự động dịch vụ của tôi không bắt đầu sau khi cài đặt

Giải pháp

Đã chèn mã này vào ProjectInstaller của tôi

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

Cảm ơn ScottTx và Francis B.


Nó không bắt đầu ngay sau khi cài đặt hoặc nó không bắt đầu khi bạn khởi động lại?
Chris Van Opstal 28/07/09

Câu trả lời:


21

Bạn có thể thực hiện tất cả điều này từ bên trong tệp thực thi dịch vụ của mình để đáp ứng với các sự kiện được kích hoạt từ quy trình InstallUtil. Ghi đè sự kiện OnAfterInstall để sử dụng lớp ServiceController để khởi động dịch vụ.

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


3
Đây là một giải pháp tốt, nhưng vẫn yêu cầu sử dụng tiện ích InstallUtil. Nếu bạn đã cung cấp InstallUtil như một phần của quá trình cài đặt của mình, điều này có ý nghĩa nhất. Tuy nhiên, nếu bạn muốn bỏ qua việc đóng gói InstallUtil, hãy sử dụng giải pháp dòng lệnh.
Matt Davis

181

Tôi đã đăng quy trình từng bước để tạo dịch vụ Windows trong C # tại đây . Có vẻ như bạn ít nhất là đến thời điểm này, và bây giờ bạn đang tự hỏi làm thế nào để bắt đầu dịch vụ sau khi nó được cài đặt. Đặt thuộc tính StartType thành Tự động sẽ khiến dịch vụ tự động khởi động sau khi khởi động lại hệ thống của bạn, nhưng nó sẽ không (như bạn đã phát hiện) tự động khởi động dịch vụ của bạn sau khi cài đặt.

Tôi không nhớ ban đầu tôi đã tìm thấy nó ở đâu (có lẽ là Marc Gravell?), Nhưng tôi đã tìm thấy một giải pháp trực tuyến cho phép bạn cài đặt và khởi động dịch vụ của mình bằng cách thực sự chạy chính dịch vụ của bạn. Đây là từng bước:

  1. Cấu trúc Main()chức năng của dịch vụ của bạn như sau:

    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. Đây là mã hỗ trợ:

    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. Tiếp tục với mã hỗ trợ ...

    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. Tại thời điểm này, sau khi bạn cài đặt dịch vụ của mình trên máy đích, chỉ cần chạy dịch vụ của bạn từ dòng lệnh (giống như bất kỳ ứng dụng thông thường nào) với -installđối số dòng lệnh để cài đặt và khởi động dịch vụ của bạn.

Tôi nghĩ rằng tôi đã đề cập đến mọi thứ, nhưng nếu bạn thấy cách này không hiệu quả, vui lòng cho tôi biết để tôi có thể cập nhật câu trả lời.


12
Lưu ý rằng giải pháp này không yêu cầu sử dụng InstallUtil.exe, vì vậy bạn không cần phải cung cấp nó như một phần của chương trình cài đặt của mình.
Matt Davis

3
Mục đích với mệnh đề trống "catch {throw;}" là gì? Ngoài ra, có lẽ không phải là ý kiến ​​hay khi ẩn các lỗi bằng "Rollback ()" vì tình huống đó về cơ bản khiến hệ thống ở trạng thái không xác định, tôi đoán là (bạn đã cố gắng cài đặt một dịch vụ, bị lỗi ở đâu đó và không thể hoàn tác nó ). Ít nhất bạn nên "cho người dùng thấy rằng có điều gì đó khó hiểu - hoặc hàm Rollback () có ghi một số thông báo vào bảng điều khiển không?
Christian.K

5
Rollback không ghi dữ liệu vào bảng điều khiển. Đối với các khối bắt trống, đó là một thứ gỡ lỗi. Tôi có thể đặt một điểm ngắt ở câu lệnh ném để kiểm tra bất kỳ ngoại lệ nào có thể xảy ra.
Matt Davis

4
Tôi nhận được Lỗi lỗi: Loại hoặc namespace tên 'YourServiceType' không thể được tìm thấy (là bạn thiếu một chỉ thị sử dụng hoặc tham khảo một hội?
Yogesh

5
YourServiceTypeProjectInstallerbạn đã thêm vào các dịch vụ, trong đó có ServiceInstallerServiceProcessInstaller
Bansi

6

Visual Studio

Nếu bạn đang tạo một dự án thiết lập với VS, bạn có thể tạo một hành động tùy chỉnh gọi là phương thức .NET để khởi động dịch vụ. Tuy nhiên, bạn không thực sự nên sử dụng hành động tùy chỉnh được quản lý trong MSI. Xem trang này .

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 hoặc Wise

Nếu bạn đang sử dụng InstallShield hoặc Wise, các ứng dụng này cung cấp tùy chọn khởi động dịch vụ. Theo ví dụ với Wise, bạn phải thêm một hành động kiểm soát dịch vụ. Trong hành động này, bạn chỉ định xem bạn muốn bắt đầu hay dừng dịch vụ.

Wix

Sử dụng Wix, bạn cần thêm mã xml sau vào thành phần dịch vụ của mình. Để biết thêm thông tin về điều đó, bạn có thể kiểm tra trang này .

<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

Bạn cần thêm Hành động tùy chỉnh vào cuối chuỗi 'Thực thi ngay lập tức' trong MSI, sử dụng tên thành phần của EXE hoặc một lô (sc start) làm nguồn. Tôi không nghĩ rằng điều này có thể được thực hiện với Visual Studio, bạn có thể phải sử dụng một công cụ tạo MSI thực cho việc đó.


4

Để bắt đầu nó ngay sau khi cài đặt, tôi tạo một tệp loạt với installutil, sau đó là sc start

Nó không lý tưởng, nhưng nó hoạt động ....


4

Sử dụng lớp .NET ServiceController để khởi động nó hoặc ra lệnh dòng lệnh để khởi động nó --- "net start servicename". Dù cách nào cũng hiệu quả.


4

Để thêm vào câu trả lời của ScottTx, đây là mã thực tế để bắt đầu dịch vụ nếu bạn đang làm theo cách của Microsoft (tức là sử dụng dự án Thiết lập, v.v.)

(xin lỗi mã VB.net, nhưng đây là những gì tôi bị mắc kẹt với)

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

Để tạo trình xử lý sự kiện ở trên, hãy chuyển đến trình thiết kế ProjectInstaller nơi có 2 bộ điều khiển. Nhấp vào điều khiển ServiceInstaller1. Chuyển đến cửa sổ thuộc tính trong các sự kiện và ở đó bạn sẽ tìm thấy sự kiện AfterInstall.

Lưu ý: Không đặt mã trên trong sự kiện AfterInstall cho ServiceProcessInstaller1. Nó sẽ không hoạt động, đến từ kinh nghiệm. :)


Mã VB.net không tệ! Đối với những người trong chúng ta, những người làm việc bằng nhiều ngôn ngữ, thật tuyệt khi không phải chuyển đổi mã từ C!
Steve Reed Sr

Cảm ơn, điều này đã giúp tôi tìm ra cách tự động bắt đầu một dịch vụ.
Charles Owen

0

Bạn có thể tìm thấy giải pháp đơn giản nhất tại đây là install-windows-service-without-installutil-exe của @ 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.