テーマ:
C# でWindowsサービス開発するときの手順まとめ。
使いやすく環境を整えるのに意外と手こずったんで。
環境は、Windows10 と Visual Studio Community 2015 です。
ソースコードがキャプチャなのはごめん。

●動かすところまで

▼プロジェクト新規作成

プロジェクト名は WindowsServerTest としておきますよ。

新規作成直後。

▼インストーラーの追加

「インストーラクラス」をプロジェクトに追加しないといけないらしい。
Service1のデザインビューで右クリックして、「インストーラーの追加」を選ぶ。
(最初これが分からなかったw)

ProjectInstaller.cs が新規作成されて、
serviceProcessInstaller と serviceInstaller のコンポーネントがデフォルトで入ってきます。


それぞれのプロパティを設定。
コンポーネントの名前の末尾に「1」が付いてるのは取っ払います。

serviceInstaller

ServiceName は、サービスの識別名になります。
StartType はインストール直後のスタートアップの種類なのでManualでいいでしょう。

続いて、serviceProcessInstaller


Account は、サービスの実行アカウントの種類なんですけど、
LocalSystem にしておかないとインストールに失敗しちゃうので、ひとまずこれで。

※「User」とかだとインストールの時にユーザ名とパスワードを求められるんだが、それを入力しても失敗してしまう…よく分からない。
http://rinta.hatenablog.com/entry/20110102/p2
これによると、アカウントのユーザ名に .\ を付ければよかったのかな?

▼本体の実装

ソリューションエクスプローラーで、Service1.csを右クリックして分かりやすい名前に変更。
とりあえずプロジェクト名と同じ「WindowsServiceTest.cs」にしておく。


次に、サービスのデザインビューを開いて、
サービスのプロパティから ServiceName を入力しておく。
これは serviceInstaller.ServiceName と合わせておく。


そして、必要なコンポーネントを配置する。今回は EventLog のみ。
左上のツールボックス>コンポーネント>EventLogをデザインビューにドラッグ&ドロップ。


EventLog のプロパティを設定。
これも名前の末尾に「1」が付いてるので取っ払う。
Source も WindowsServiceTest に合わせます。


サービスのソースを開くと、OnStart と OnStop がありますね。
賢い読者は、これがどういう意味か分かりますよね。
とりあえずログが出るように書いておきます。
(別にこんな事しなくても、起動・停止のログは自動で取られるが)


あとはビルドすれば、bin/Debug 配下にexeファイルが出来ます。

▼動作確認

実行するには、サービスをインストールしないといけないのです。
そのためにまず、開発環境へのパスが通ったコマンドプロンプトを開きます。
コマンドプロンプトは管理者権限で実行。
※なお、先にこの記事を「他のマシンにインストール」まで読み進めて頂いた方が幸せになれるかもしれませんw

スタートメニュー>Visual Studio 2015>開発者コマンドプロンプト for VS2015 を右クリック>その他>管理者として実行


続いてサービスのexeのあるディレクトリへ移動して、以下のコマンドを実行。
installutil [exeファイル]

下記のように出れば成功。


管理ツールの「サービス」を見て、登録されているか確認してみよう!
サービスを起動、停止すれば、イベントログが記録されます。
起動ログ

停止ログ


なお、サービスのアンインストールは以下のコマンドで。
installutil /u [exeファイル]

●デバッグ

実はこのままIDEから実行しても起動できなくて、デバッグさせてもらえません。
なので、このままだとサービスの起動・停止をして
イベントログに色々吐き出してテストするしかないんですが、
コンソールアプリケーションとして実行すれば、普通にデバッグできるので便利です。

プロジェクトのプロパティを開いて、出力の種類をコンソールアプリケーションに変更。


そして、ソース上で、「コンソール」か「サービス」かの分岐を作ります。
Environment.UserInteractive で判断します。
ついでに、Main関数で引数を受け付けるようにしときますね。


コンソールの場合は、Console.Read() でキー入力を受け付けて、
何かキーが押されたらサービスを停止するようにします。
なお、サービスクラスの OnStart(), OnStop() メソッドは直接呼び出すことはできません。
(アクセシビリティが protected のため)
そのため、以下のようにサービスクラス側で、public なメソッドでラッピングしてあげます。


これで、コマンドプロンプトからサービスのexeを直接起動できますし、
IDEから実行したときも、デバッガが動くはずです。
一度ブレークポイントを置いて試してみてください。

その他のデバッグのやり方は、
・起動したあとVisualStudioのメニューから デバッグ>プロセスにアタッチ を選択する
・OnStart() で Debugger.Launch() を呼び出す
などがあるのですが、コンソールアプリケーションにしてしまう方法が一番スマートだと思います。

●他のマシンにインストール

サービスのインストール手順は上で説明しましたが、
じゃあ、開発環境の入っていないマシンではどうすんの?っていう話。
開発者コマンドプロンプトなんて無いですよね。
一応、.Net framework が入ってれば installutil が使えるのですが、パスが遠いし(笑)
そうなると、調べてる最中に見つけた「自己登録型」にするのが良いかなと思いまして。

ManagedInstallerClass っていうクラスを使うと、
プログラムからサービスのインストール/アンインストールが出来るんです。
内部では installutil を呼び出してるっぽいですけど。

WindowsServiceTest.exe をコマンドプロンプトから実行するときに、
パラメータが "/i" でインストール、"/u" でアンインストールするように作っちゃいます。
かこった部分が追記。


見て頂ければ、だいたい何をやってるか見当がつくと思います。
WindowsServiceTest.exe /i でインストール、
WindowsServiceTest.exe /u でアンインストールされることを確認してみて下さい。

●シャットダウン時の挙動

マシンがシャットダウンされるときって、何か重要な処理をしている場合に
安全に落とせるように、その処理が完了するまで待ったりしたいと思うんですけど
そのためには、サービスクラスの CanShutDown プロパティを True にして

protected override void OnShutdown() {
  //StopTask();
}

みたいなコードを書いたら出来るよ、と色んな所に書いてあるんですけど
それがちっとも動かなくて。何回再起動したことか。。。

原因は分からなかったんですが、
プレシャットダウンを検知するカスタムイベントを受信できるようにしたら
解決できたので。以下のURL参考にしました。
http://www.sivachandran.in/2012/03/handling-pre-shutdown-notification-in-c.html

まずサービスクラスのコンストラクタの処理。


カスタムコマンドを受け付けるところ。


StopTask() のところで、タスクの終了を wait してみると、
サービス停止のイベントログが wait から抜けたあとに出てることを確認できると思います。

コードがキャプチャでほんとごめん。
AD
いいね!した人  |  コメント(0)  |  リブログ(0)

らむてがさんの読者になろう

ブログの更新情報が受け取れて、アクセスが簡単になります

AD

ブログをはじめる

たくさんの芸能人・有名人が
書いているAmebaブログを
無料で簡単にはじめることができます。

公式トップブロガーへ応募

多くの方にご紹介したいブログを
執筆する方を「公式トップブロガー」
として認定しております。

芸能人・有名人ブログを開設

Amebaブログでは、芸能人・有名人ブログを
ご希望される著名人の方/事務所様を
随時募集しております。