→[[OS関連]]

→.NETプログラミング

→WindowsAPI関連

#contents


-※ Visual Studio .NET 2005での開発として記述する

*参考にするヘルプ [#zc9adb08]
-Visual Stuidoプログラマーズガイドの「Windows サービス アプリケーション 」の章
-ServiceBaseクラス
-ServiceProcessInstallerクラス
-ServiceInstallerクラス
-ServiceControllerクラス


*予備知識 [#nb46a995]
-動作アカウント
--既定では、サービスはシステム アカウントで実行されます。このシステム アカウントは、管理者アカウントとは異なります。システム アカウントの権限は変更できません。ただし、ServiceProcessInstaller を使用して、サービスを実行するときに使用するユーザー アカウントを指定できます(serviceProcessInstaller.Account,Password,Usernameに値を設定する)。


*Windowsサービス作成時のルール [#hdc6b89e]
**必須事項 [#e7856b2e]
-MainメソッドでServiceBase.Run()を呼ぶ必要がある(プロジェクト作成時に自動生成される)
-インストールコンポーネントを必ず作成する必要がある(下で詳述)
--※インストールコンポーネントとは、サーバーへのサービスのインストールと登録を行う機能
-ウインドウステーションが非I/Oなのでサービスからメッセージボックスは表示できない。呼び出すと処理が止まるので呼んではいけない
-サービスのクラス(ServiceBaseから派生したクラス)のServiceNameプロパティにセットする値はProjectInstallerクラス(Installerから派生したクラス)のServiceNameと一緒でなくてはならない。特に後から変更する場合に注意が必要

**推奨事項 [#wa3587aa]
-エラー出力などはイベントログに対して行うのが望ましい


*サービスのインストールコンポーネントを作成するには [#m91030e0]
-ソリューション エクスプローラで Service1.vb、Service1.cs、または Service1.jsl を右クリックし、[デザイナの表示] をクリックします。 
-デザイナの背景をクリックして、サービスの内容ではなくサービス自体を選択します。
-デザイナにフォーカスを置いた状態で右クリックし、[インストーラの追加] をクリックします。 
-既定では、2 つのインストーラを含むコンポーネント クラスがプロジェクトに追加されます。このコンポーネントは ProjectInstaller という名前で、サービス用のインストーラと、サービスの関連プロセス用のインストーラを含んでいます。 
-ProjectInstaller のデザイン ビューで、[serviceInstaller1] をクリックします。
-[プロパティ] ウィンドウで、[ServiceName] プロパティを <自分の作ったサービスプロジェクトの名前> に設定します。
-[StartType] プロパティを Automatic に設定します。
-デザイナで、[serviceProcessInstaller1] をクリックします。
-[Account] プロパティを LocalService に設定します。これにより、サービスがインストールされ、ローカル サービス アカウントで実行されます。 
-serviceInstaller1のServiceNameプロパティにセットした文字列がコントロールパネルのサービスの「名前」の欄に表示される。ここを変更したらサービスクラスのServiceNameプロパティもあわせて変更すること。
-【疑問】どうせやらないといけないならなぜ最初にテンプレから生成したときに作られるようにしないのだろう?(もしかして機能上できないのか?)


*サービスの動作定義 [#e8c899c3]
-以下のようなServiceBaseのメソッドをオーバライドする(ヘルプより)
-OnStart: サービスの実行を開始したときのアクションを示します。サービス本来の処理は、このプロシージャに記述する必要があります。 
-OnPause: サービスを一時停止したときの動作を示します。 
-OnStop :サービスの実行を停止したときの動作を示します。
-OnContinue: 一時停止したサービスを再開したときの動作を示します。 
-OnShutdown :実行中のサービスの、システムがシャットダウンする直前の動作を示します。 
-OnCustomCommand:サービスがカスタム コマンドを受信したときの動作を示します。カスタム コマンドの詳細については、MSDN オンラインを参照してください。 
-OnPowerEvent:低電力モードやサスペンド モードなど、電源管理イベントを受信したときのサービスの応答を示します。

-OnStart()とOnStop()のオーバライドは必須。あとは任意

*OnStartで停止するには [#d86c0da4]
-ApplicationExceptionをthrowする
-参考URL:http://bbs.wankuma.com/index.cgi?mode=al2&namber=14866&KLOG=31


*System.Windows.Forms.Timerのイベントはサービスでは使えない [#m5f5423a]
-参照URL:http://support.microsoft.com/kb/820639/ja
-サービスで一定間隔ごとになんらかの処理をしたい場合、タイマを使いたくなるが…
-Windows フォーム Timer コンポーネントは、 Windows フォーム環境用に設計されています。 Windows フォーム Timer コンポーネントは、サーバー環境用に設計されていません。 したがって、タイマを Windows サービスで使用する場合、イベントを発生しない
-この問題を解決するために、 System.Windows.Forms 空間からの Windows フォーム タイマの代わりに System.Timers 空間からサーバーのタイマを使用します。

-…とあるのだがSystem.Timers.Timerにも実は問題があるとのこと
-参照URL:http://support.microsoft.com/kb/842793/ja
-Elapsedイベントハンドラの中でStop()メソッドを呼ぶとダメらしい(Enabledのon/offでやればOKなようだ)
-System.Threading.Timerを使えとのことだが、使いにくいのでSystem.Timers.Timerの方がいいと思われる

-[[サーバベースのタイマの概説>http://msdn.microsoft.com/ja-jp/library/tb9yt5e6.aspx]]

-タイマを使うのではなくスレッドを起こしてインターバル分Sleep()した方がいいかも…
-参考:[[Windowsサービスで処理が実行されない>http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=35585&forum=7]]

*デバッグ方法 [#u49cb641]
-直接ステップインはできない。起動してからプロセスにアタッチする
-なので、ビジネスロジックはdllで作成して開発中はテストドライバから呼んでよくテストしておき、最後にサービス化するという開発手順が良いと思う


*サービス用のセットアッププロジェクトの作り方 [#iffae3e0]
-ソリューションにセットアッププロジェクトを追加
-プロジェクトを右クリック→追加→プロジェクト出力ダイアログ表示
-ダイアログでサービスのプロジェクトを選択
-ダイアログの一覧で「プライマリ出力」を選択→OK
-プロジェクトを右クリック→表示→カスタム動作→カスタム動作エディタ表示
-カスタム動作エディタ上の「カスタム動作」を右クリック→カスタム動作の追加→「プロジェクトから項目を選択」ダイアログが表示
-一覧の「アプリケーションフォルダ」を開き「XXXX(アクティブ)のプライマリ出力」をクリック→OK
-プロジェクトをビルド
-以上で、セットアップと同時にサービスとして登録されるようなmsiが作られる
-ポイントはカスタム動作でプライマリ出力を追加するところのようだ。インストールコンポーネントを見つけて自動的にサービスを登録してくれる模様
-このセットアップがあれば、InstallUtil.exeによるセットアップ作業は不要となる

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS