programing

지속적으로 실행되는 Windows 서비스

projobs 2021. 1. 17. 10:22
반응형

지속적으로 실행되는 Windows 서비스


나는 ProxyMonitor 라는 Windows 서비스를 만들었고 현재 서비스가 내가 원하는 방식으로 설치 및 제거되는 단계에 있습니다.

그래서 다음과 같이 응용 프로그램을 실행합니다.

C:\\Windows\\Vendor\\ProxyMonitor.exe /install

꽤 자명 한 다음 services.msc서비스를 시작하고 시작했지만 이렇게하면 다음 메시지가 표시됩니다.

로컬 컴퓨터의 프록시 모니터 서비스가 시작된 다음 중지되었습니다. 수행 할 작업이 없으면 일부 서비스가 자동으로 중지됩니다 (예 : 성능 로그 및 경고 서비스).

내 코드는 다음과 같습니다.

public static Main(string[] Args)
{
    if (System.Environment.UserInteractive)
    {
        /*
            * Here I have my install logic
        */
    }
    else
    {
        ServiceBase.Run(new ProxyMonitor());
    }
}

그리고 ProxyMonitor 클래스 내에 다음이 있습니다.

public ProxyMonitor()
{
}

protected override void OnStart(string[] args)
{
    base.OnStart(args);
    ProxyEventLog.WriteEntry("ProxyMonitor Started");

    running = true;
    while (running)
    {
        //Execution Loop
    }
}

그리고 변수를 onStop()다음으로 변경합니다 .runningfalse

변경 사항 등을 추적해야하는 네트워크를 모니터링해야하므로 서비스를 지속적으로 활성화하려면 어떻게해야합니까?


업데이트 : 1

protected override void OnStart(string[] args)
{
     base.OnStart(args);
     ProxyEventLog.WriteEntry("ProxyMonitor Started");

     Thread = new Thread(ThreadWorker);
     Thread.Start();
 }

내에서 ThreadWorker내가 가진 ProxyEventLogger.WriteEntry("Main thread entered")해고하지 않는.


OnStart()콜백은 모든 작업이 수행 될 스레드를 킥오프 할 것이다, 그래서 적시에 반환해야합니다. 수업에 다음 필드를 추가하는 것이 좋습니다.

using System.Threading;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;

_thread필드는 콜백 System.Threading.Thread에서 생성 객체에 대한 참조를 보유합니다 OnStart(). _shutdownEvent필드에는 서비스 종료시 실행을 중지하도록 스레드에 신호를 보내는 데 사용되는 시스템 수준 이벤트 구성이 있습니다.

에서 OnStart()콜백 만들고 스레드를 시작합니다.

protected override void OnStart(string[] args)
{
     _thread = new Thread(WorkerThreadFunc);
     _thread.Name = "My Worker Thread";
     _thread.IsBackground = true;
     _thread.Start();
}

WorkerThreadFunc이 작업을 수행하려면 이름이 지정된 함수가 필요합니다 . System.Threading.ThreadStart델리게이트 서명 과 일치해야 합니다.

private void WorkerThreadFunc()
{
}

이 함수에 아무것도 넣지 않으면 스레드가 시작되고 즉시 종료되므로 작업을 수행하는 동안 기본적으로 스레드를 유지하는 로직을 거기에 넣어야합니다. 이것은 _shutdownEvent편리한 곳입니다.

private void WorkerThreadFunc()
{
    while (!_shutdownEvent.WaitOne(0)) {
        // Replace the Sleep() call with the work you need to do
        Thread.Sleep(1000);
    }
}

while 루프는에서 ManualResetEvent"설정"여부를 확인합니다 . false위와 같이 객체를 초기화 했으므로이 검사는 false를 반환합니다. 루프 안에서 우리는 1 초 동안 수면을 취합니다. 이 작업을 프록시 설정 모니터링 등 필요한 작업으로 바꾸고 싶을 것입니다.

마지막으로, OnStop()Windows 서비스 콜백에서 스레드 실행 중지 신호를 보내려고합니다. 이것은 _shutdownEvent.

protected override void OnStop()
{
     _shutdownEvent.Set();
     if (!_thread.Join(3000)) { // give the thread 3 seconds to stop
         _thread.Abort();
     }
} 

도움이 되었기를 바랍니다.


OnStart서비스 컨트롤러가 서비스가 실제로 시작되었음을 인식하려면 핸들러 를 종료해야 합니다. 원하는대로 작동하도록하려면 간격을두고 틱하고 틱할 때 처리하는 타이머를 시작할 수 있습니다.

편집하다:

System.Diagnostics.Debugger.Launch ()를 OnStart넣어 무슨 일이 일어나고 있는지 확인하십시오 (그리고 중단 점을 ThreadWorker). #if DEBUG배포되지 않도록 포장하는 것이 좋습니다 .

나는 또한 당신이 당신 Thread의 이름을 밝히지 않는다는 것을 깨달았습니다 .

 Thread myThread = new Thread(ThreadWorker);
 myThread.Start();

확실히 메서드에 while루프를 추가하지 않습니다 OnStart. 이것은 서비스가 OnStart메소드 에서 안전하게 종료 할 수 없기 때문에 서비스가 시작되지 않았다는 것을 OS에 알려줄 것입니다 . 나는 일반적으로 방법 Timer에서 활성화 되는 것을 만듭니다 OnStart. 그런 다음 Ticks메서드에서 응용 프로그램을 실행하기 위해 필요한 메서드를 호출합니다.

또는 다음을 수행 할 수 있습니다.

// The main entry point for the process 
static void Main() 
{ 
    System.ServiceProcess.ServiceBase[] ServicesToRun; 
    ServicesToRun = new System.ServiceProcess.ServiceBase[] { new WinService1() }; 
    System.ServiceProcess.ServiceBase.Run(ServicesToRun); 
} 

Windows 서비스에 대한 자세한 내용은 여기 에서 골격 예제를 얻을 수 있습니다 .


콘솔 앱을 사용하여 시연 된 샘플 코드입니다. 도움이 되길 바랍니다 ..

 class Program
{
    private static CancellationTokenSource _cancellationTokenSource;
    private static ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
    private static Thread _serviceStartThread;
    private static Thread _serviceStopThread;

    private static int workcounter = 0;
    static void Main(string[] args)
    {

        _cancellationTokenSource = new CancellationTokenSource();
        _serviceStartThread = new Thread(DoWork);
        _serviceStopThread = new Thread(ScheduledStop);
        StartService();
        StopService();
    }

    private static void StartService()
    {
        _serviceStartThread.Start();

    }

    private static void StopService()
    {
        _serviceStopThread.Start();
    }


    /// <summary>
    /// Triggers a cancellation event for stopping the service in a timely fashion.
    /// </summary>
    private static void ScheduledStop()
    {
        while (!_shutdownEvent.WaitOne(0))
        {
            if (workcounter == 10)
            {
                _cancellationTokenSource.Cancel();
            }
        }
    }

    /// <summary>
    /// Represents a long running Task with cancellation option
    /// </summary>
    private static void DoWork()
    {

        while (!_shutdownEvent.WaitOne(0))
        {
            if(!_cancellationTokenSource.Token.IsCancellationRequested)
            {
                workcounter += 1;
                Console.Write(Environment.NewLine);
                Console.Write("Running...counter: " + workcounter.ToString());
                Thread.Sleep(1000);//Not needed, just for demo..
            }
            else
            {
                Console.Write(Environment.NewLine);
                Console.Write("Recieved cancellation token,shutting down in 5 seconds.. counter: " + workcounter.ToString());
                _shutdownEvent.Set();
                Thread.Sleep(5000);//Not needed, just for demo..
            }

        }
    }
}

Windows 서비스 유형의 솔루션에서 새 프로젝트를 생성하지 않는 이유는 무엇입니까? 이는 서비스 시작 / 중지 이벤트에 대한 핸들러를 포함하여 구현해야하는 모든 구조를 설정합니다.

ReferenceURL : https://stackoverflow.com/questions/4864673/windows-service-to-run-constantly

반응형