설치 직후 .NET Windows 서비스를 시작하는 방법은 무엇입니까?


88

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

ScottTx와 Francis B.


설치 후 바로 시작되지 않거나 재부팅 할 때 시작되지 않습니까?
Chris Van Opstal

답변:


21

InstallUtil 프로세스에서 발생한 이벤트에 대한 응답으로 서비스 실행 파일 내에서이 모든 작업을 수행 할 수 있습니다. ServiceController 클래스를 사용하여 서비스를 시작하려면 OnAfterInstall 이벤트를 재정의하십시오.

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


3
이것은 좋은 해결책이지만 여전히 InstallUtil 유틸리티를 사용해야합니다. 설치의 일부로 InstallUtil을 이미 제공하고 있다면 이것이 가장 합리적입니다. 그러나 InstallUtil을 패키징하지 않으려면 명령 줄 솔루션을 사용하십시오.
Matt Davis

181

여기 에 C #에서 Windows 서비스를 만드는 단계별 절차를 게시했습니다 . 적어도이 시점까지 들리는 것 같고 이제 서비스가 설치된 후 시작하는 방법이 궁금합니다. 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명령 줄 인수를 사용 하여 명령 줄 (일반 애플리케이션과 마찬가지로)에서 서비스를 실행하여 서비스 를 설치하고 시작합니다.

내가 모든 것을 다룬 것 같지만 이것이 작동하지 않는 경우 알려 주시면 답변을 업데이트 할 수 있습니다.


12
이 솔루션은 InstallUtil.exe를 사용할 필요가 없으므로 설치 프로그램의 일부로 제공 할 필요가 없습니다.
Matt Davis

3
빈 "catch {throw;}"절이있는 이유는 무엇입니까? 또한 "Rollback ()"에 의해 실패를 숨기는 것은 아마도 그 상황이 기본적으로 시스템을 정의되지 않은 상태로 남겨두기 때문에 좋은 생각이 아닐 것입니다 (서비스를 설치하려고 시도했지만 중간에 실패했으며 실행 취소 할 수 없었습니다). ). 적어도 뭔가 수상한 것이 있음을 사용자에게 "보여"야합니다. 아니면 Rollback () 함수가 콘솔에 일부 메시지를 작성합니까?
Christian.K

5
롤백은 콘솔에 데이터를 기록합니다. 빈 catch 블록은 디버깅 작업입니다. 발생 가능한 예외를 검사하기 위해 throw 문에 중단 점을 넣을 수 있습니다.
Matt Davis

4
오류가 발생합니다. 오류 : 유형 또는 네임 스페이스 이름 'YourServiceType'을 찾을 수 없습니다 (using 지시문 또는 어셈블리 참조가 누락 되었습니까?
Yogesh

5
YourServiceType는 IS ProjectInstaller당신은 포함 서비스에 추가 ServiceInstaller하고ServiceProcessInstaller
bansi

6

비주얼 스튜디오

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

EXE의 구성 요소 이름 또는 배치 (sc start)를 소스로 사용하여 MSI의 'ExecuteImmediate'시퀀스 끝에 사용자 지정 작업을 추가해야합니다. Visual Studio에서는 이것이 가능하지 않다고 생각합니다. 실제 MSI 저작 도구를 사용해야 할 수도 있습니다.


4

설치 후 바로 시작하기 위해 installutil 다음에 sc start를 사용하여 배치 파일을 생성합니다.

이상적은 아니지만 작동합니다 ....


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 디자이너로 이동합니다. ServiceInstaller1 컨트롤을 클릭합니다. 이벤트 아래의 속성 창으로 이동하면 AfterInstall 이벤트를 찾을 수 있습니다.

참고 : 위 코드를 ServiceProcessInstaller1의 AfterInstall 이벤트 아래에 두지 마십시오. 경험에서 오는 것은 작동하지 않습니다. :)


VB.net 코드는 나쁘지 않습니다! 여러 언어로 작업하는 사람들에게는 C에서 코드를 변환하지 않아도되는 것이 좋습니다!
Steve Reed Sr

감사합니다. 서비스를 자동으로 시작하는 방법을 알아내는 데 도움이되었습니다.
Charles Owen

0

가장 쉬운 해결책은 @ Hoàng Long의 install-windows-service-without-installutil-exe 에서 찾을 수 있습니다.

@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.