.NET を理解する7
サービスの作成
.NET のサービスを作成するにあたり、色々調べてみる。
- ServiceBase クラスを継承してサービス作る
- ServiceController クラスで .NET アプリからサービスの開始停止を制御できる
- ServiceControllerPermission サービス コントローラに対するコード アクセス セキュリティ アクセス許可を制御できるようにします。
- ServiceInstaller でインストール時のサービス名とか、表示とかをいじる。
- ServiceProcessInstaller サービスが動作するときの設定とか、アカウント、ユーザ権限などを操作します。
- ServiceChangeDescription ターミナルサービスのセッション変更の理由を示します。
- ServiceChangeReason ターミナル サービスのセッション変更の通知理由を示します。
と、クラスの概要。
まぁなんとなくはわかるにしても、作らなくてはだめぽ。
ということで、ExpressEdition でもできるサービス開発をする。
俺俺サービス作ってみる。
基本的にバックグラウンドで実行されるサービスってのを作ってみる。
Windows サービス作る場合、ServiceBase を継承して、適当なイベントメソッドをオーバライドして作る。
このサイトから1分おきにタイトル拾ってファイルに書き込むサービスを作る。
手元に VisualStudio2008 Standard しかねえwプロジェクトテンプレが無いが、根性でどうにかする。
class BlogLoader { public static string[] GetNazogengoTitles() { XElement blog = XElement.Load("http://d.hatena.ne.jp/white-azalea/rss"); XNamespace xmlns = "http://purl.org/rss/1.0/"; var titles = from p in blog.Elements() where p.Name.LocalName == "item" select p.Element(xmlns + "title").Value; return titles.ToArray(); } } public class SampleService : System.ServiceProcess.ServiceBase { System.Timers.Timer timer; static void Main(string[] args) { System.ServiceProcess.ServiceBase[] ServicesToRun = new System.ServiceProcess.ServiceBase[] { new SampleService() }; System.ServiceProcess.ServiceBase.Run(ServicesToRun); Console.ReadLine(); } protected override void OnStart(string[] args) { base.OnStart(args); timer = new System.Timers.Timer(60000); timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); timer.Enabled = true; } void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { string filePath = this.Application.info.DirectoryPath.ToString() + "\\Files"; string[] results = BlogLoader.GetNazogengoTitles(); // ディレクトリが存在するか if (!System.IO.Directory.Exists(filePath)) { System.IO.Directory.CreateDirectory(filePath); } // ファイル名を作成 filePath = filePath + "\\" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt"; // ファイル作成と書き込み using (System.IO.StreamWriter writer = new System.IO.StreamWriter(filePath)) { foreach (string single in results) { writer.WriteLine(single); } } } protected override void OnStop() { base.OnStop(); timer.Enabled = false; } }
サービスプロセスを作ったところで、このままではインストールもままならない。
ので、根性でサービスインストーラを作る。これで InstallUtil でどうにかできる。
namespace ServiceInstaller { using System; using System.ServiceProcess; using System.Configuration.Install; using System.Collections.Generic; [System.ComponentModel.RunInstaller(true)] public class ProjectInstaller : Installer { private System.ServiceProcess.ServiceInstaller serviceInstaller; private ServiceProcessInstaller processInstaller; // 以下にこのプロジェクトが依存するサービスを記述 private string[] param = new string[] { }; public ProjectInstaller() { processInstaller = new ServiceProcessInstaller(); serviceInstaller = new System.ServiceProcess.ServiceInstaller(); // Service will run under system account processInstaller.Account = ServiceAccount.LocalSystem; // Service will have Start Type of Automatic serviceInstaller.StartType = ServiceStartMode.Automatic; serviceInstaller.ServicesDependedOn = this.param; serviceInstaller.ServiceName = "NazoChecker"; serviceInstaller.Description = "謎言語使いの言動を逐次チェックします。"; this.Installers.Add(serviceInstaller); this.Installers.Add(processInstaller); } } }
かなり根性。
そしてサクッとインストール!
PATH=%PATH%;C:\Windows\Microsoft.NET\Framework\v2.0.50727;
installutil SampleService.exe
うごけぇええええええ!!!
インストール段階で例外が発生しました。 System.Security.SecurityException: ソースが見つかりませんでしたが、いくつかまた はすべてのログを検索できませんでした。アクセス不可能なログ: Security
orz |
WindowsXP はコレで動くのですが、Windows7/Vista 連中はセキュリティががががが、、、、、
cmd.exe を管理者権限で再実行。
尚、アンインストールは
installutil /u SampleService.exe
Windows7 で this.Application.info.DirectoryPath.ToString() のディレクトリは、「C:\Windows\System32\」っぽい。
たぶん XP とかもではないかなー