C#で簡易的なWindowsサービスを作ってみる

chakemiです。 本日は、前回の続きで簡易的なWindowsサービスを作成してみたいと思います。

開発環境

  • VisualStudio2010
  • WindowsXP SP3 .Net Framework4

前回までで、何も起動しないサービスを登録するとこまでは出来ました。

今回は、実際に処理を実装し、サービスとして開始、停止をしてみます。 まずは、簡単なとこから、サービスの開始、停止時にアプリケーションのイベントログを記録するようにしてみます。

開始と停止の際に処理される、Onstartメソッド、Onstopメソッドで、EventLogクラスのWriteEntryメソッドを実行します。

1
2
3
4
5
6
7
8
9
protected override void OnStart(string[] args)
{
    EventLog.WriteEntry(String.Format("OnStart: {0}", DateTime.Now));
}

protected override void OnStop()
{
    EventLog.WriteEntry(String.Format("OnStop: {0}", DateTime.Now));
}

実際にインストールし、サービスを開始、停止してみます。

とりあえず、独自のフォーマットのイベントログが記録出来ました。 では、本題に入って、実際に自作のサービスを登録してみます。

今回は、簡単なwebサーバを実装してみたいと思います。

サービスを実行するのに、OnStartメソッドで開始時に実行したい処理を書けば言い訳ですが、 OnStartメソッドはサービスが指定時間内に、正常起動したことをWindows側へ返す必要があるため ここでは、メインループを別スレッドで実行するように記述します。

HTTPリクエストを処理する簡単なメインループを作成します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//メインループ 簡易webサーバ
private Thread serviceThread;
private volatile bool serviceStop = false;

private void Run()
{
    string root = @"c:\www";
    string prefix = "http://*:8080/";

    HttpListener listener = new HttpListener();
    listener.Prefixes.Add(prefix);
    listener.Start();

    while (!serviceStop)
    {
        HttpListenerContext context = listener.GetContext();
        HttpListenerRequest request = context.Request;
        HttpListenerResponse response = context.Response;

        string path = root + request.RawUrl.Replace("/", "\\");

        if (File.Exists(path))
        {
            byte[] content = File.ReadAllBytes(path);
            response.OutputStream.Write(content, 0, content.Length);
        }
        response.Close();
    }
    listener.Close();
}

別スレッドでループを開始します。

1
2
3
4
5
6
7
private Thread serviceThread;
protected override void OnStart(string[] args)
{
    serviceThread = new Thread(Run);
    serviceThread.Start();
    EventLog.WriteEntry(String.Format("OnStart: {0}", DateTime.Now));
}

ここでは、処理を簡単にするため、OnStopメソッドでスレッドを強制的に終了してます。

1
2
3
4
5
6
protected override void OnStop()
{
    serviceStop = true;
    serviceThread.Abort();
    EventLog.WriteEntry(String.Format("OnStop: {0}", DateTime.Now));
}

ルートに指定したディレクトリに適当にhtmlファイルを用意し、実際にサービスを開始してアクセスしてみます。

とりあえず、出来上がり♪

Comments