→[[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にも実は問題がある!''
-…とあるのだがSystem.Timers.Timerにも実は問題があるとのこと
-参照URL:http://support.microsoft.com/kb/842793/ja
-Elapsedイベントハンドラの中でStop()メソッドを呼ぶとダメらしい
-System.Threading.Timerを使えとのこと
-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で作成して開発中はテストドライバから呼んでよくテストしておき、最後にサービス化するという開発手順が良いと思う



トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS