Windowsサービスを楽に開発~TopShelf~

0.前置き

Windowsサービスの開発に利用できるTopShelfという.NETのライブラリーを紹介します。
TopShelfを利用すれば、Windowsサービスのテストとインストールが実施しやすくなります。
ポイントとしては以下の2つがあります。

・コンソールアプリケーションとしてテストを実施できる。
・InstallUtilを利用しなくても簡易にSCMにインストールができる。

というわけで、サンプルを書きながら細かいことは説明します。

1.TopShelfの紹介

TopShelfはOSSで開発されているWindowsサービス構築用のライブラリーです。
Windowsサービス開発に必要となる、テスト支援、設定支援、インストール支援などを
主な機能として持っています。

プロジェクトのサイトはこちら(TopShelf Project)です。
GitHubでの開発はこちら(Topshelf / Topshelf)です。

2.インストール

VisualStudioで開発します。
プロジェクトは「コンソールアプリケーション」を利用ます。
そのあとNuGetで「TopShelf」パッケージを追加してください。

nuget

3.実際に使ってみる

下記の通りサンプルを作りました。
1秒(1000ms)ごとにログ(”I am fine”)を出力するプログラムです。

「Program.cs」以下の通り。

using Topshelf;

namespace TopShelfSample
{
    public class Program
    {
        public static void Main()
        {
            HostFactory.Run(x =>
            {
                //ロジックがあるクラスへの参照
                x.Service<Beat>(s =>
                {
                    s.ConstructUsing(name => new Beat());
                    s.WhenStarted(tc => tc.Start());
                    s.WhenStopped(tc => tc.Stop());
                });
                
                //Windowsサービスの設定
                x.RunAsLocalSystem();
                x.SetDescription("Just beating program");
                x.SetDisplayName("BeatingProgram");
                x.SetServiceName("BeatingService");
            });
        }
    }
}

ロジックが入っているクラスは以下の通り「Beat.cs」。

using System.Timers;
using NLog;

namespace TopShelfSample
{
    public class Beat
    {
        private readonly Timer _timer;
        private readonly Logger _logger = LogManager.GetCurrentClassLogger();
        public Beat()
        {
            _timer = new Timer(1000)
            {
                AutoReset = true
            };
            _timer.Elapsed += (sender, eventArgs) => _logger.Info("I am fine");
        }
        public void Start() { _timer.Start(); }
        public void Stop() { _timer.Stop(); }
    }
}

デバッグ実行
VisualStudioでF5を押して、デバッグ実行してみます。
ただのコンソールアプリケーションのように実行できます。
(ここが便利!)

console

インストール
インストールしてみます。
ビルド後に生成されるEXEの引数に「install」オプションを付ければよいです。

TopShelfSample.exe install

結果、下記のイメージのようにサービスをインストールできました。

service

この状態で「開始」を押下すればサービスとして実行されます。
実行結果は下記の通り。

log

4.サンプルを書いてみての補足

Windowsサービスに対する設定は他にもいくつか実施できます。
・スタートアップの種類(自動/手動/遅延起動)
・ログオンアカウント(実行アカウント)の種類
・依存関係の設定(サービス名を指定できる)
 (SQL Serverが起動していないと、起動してはダメとか)
詳しくは、Configuring Topshelfを読むと良いです。

5.サンプルコード

今回作ったサンプルはGitHubにホスティングしてあります。
TopShelfのサンプルアプリケーション

6.最後に

これを使うととにかくデバッグが楽です。
ちょっと前から使ってましたけど、日本語の情報がなかったので書いてみました。
ぜひ試してみてください。

Windowsや.NETの元号管理について



-1. 前置きの前置き

===2018年1月13日追記===
2017年に日本マイクロソフトの公式ブログ、Japan New Era Name Support Blogが開設されました。こちらでマイクロソフト社製品に関する公式な対応方法が更改される予定です。ぜひそちらも参考の上、ご準備ください。

0.前置き

新年あけましておめでとうございます。今年は、1年間で24エントリー書くのが目標です!

さて、さっそく内容に入ります。
年を表現する方法には、日本の場合ですと、西暦と和暦を利用します。
和暦は、「平成」や「昭和」などの元号を用いて表記します。
ここで問題となるのが、平成が終わったら次の元号はどこに誰が定義するのかという話です。

結論から言いますと、Windows 7や、.NET 4以降では、レジストリーで管理されています。
元号に追加が発生した場合は、Windows Updateの更新によって対応されるわけです。
今回のエントリーでは、.NETの元号管理の面からその挙動を確認してみたいと思います。

1..NETでの和暦表示

.NETで和暦表示を行う場合、System.Globalization.JapaneseCalendar クラスを利用します。
例えば、以下のようにして、和暦を出力することができます。

var cultureInfo = new CultureInfo("ja-jp")
                        {
                            DateTimeFormat = { Calendar = new JapaneseCalendar() }
                        };
Console.WriteLine(DateTime.Now.ToString("ggyy年MM月dd日", cultureInfo));

出力すると以下の通りです。

> 平成25年01月13日

2.レジストリーでの元号管理

前置きに書いた通り、Windows 7以降では、レジストリーに西暦と和暦(元号)の対応が登録されています。

PS HKLM:\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese> Get-ChildItem

    Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese

Name                    Property
----                    --------
Eras                    1868 01 01 : 明治_明_Meiji_M
                        1912 07 30 : 大正_大_Taisho_T
                        1926 12 25 : 昭和_昭_Showa_S
                        1989 01 08 : 平成_平_Heisei_H

JapaneseCalenderもここを参照しているわけです。
なお、このレジストリー値は、元号が追加になった際には、Windows Updateにて対応されます。
テスト等で一時的に元号を増やして確認したい場合は、ここに新しいアイテムを追加します。
(レジストリー値を触る場合は、自己責任で注意して行ってください。間違えると大変です。)
試しに、2013年1月1日から「新元号」という元号を追加してみました。

New-ItemProperty "Eras" "2013 01 01" -value "新元号_新_NEWERA_N"

このアイテムを追加した状態で、先ほどのプログラムを動かすと、以下の出力になります。

> 新元号01年01月13日

3.最後に

意外に簡易な方法で管理されていてびっくりです。
調べる前はどのように管理されているかわからなかったので、独自のユーティリティを作ってしまうところでした…。

それと今回はレジストリー値を触るときに、regeditではなくて、PowerShellを利用しました。
なんでもかんでもPowerShellから触れるのは楽でよいです。PSドライバーの話などは以下のエントリーが詳しいのでぜひ読んでみてください。
GUIユーザーのためのPowerShell入門 28 レジストリ更新コマンドを作る(1)

今回の内容のもと情報はMSDNに記載があります。
こちらのページを参考にしてください。
MSDN:「Era Handling for the Japanese Calendar (Windows)

初めてのpsake ~PowerShelを使ったビルドツール~

0.前置き

初めてAdvent Calenderに挑戦しています。
私の担当は、「PowerShell Advent Calendar 2011」の14日目です。
Webアプリケーション開発の効率化のためによくPowerShellを利用しますが、ブログで取り扱うのは初めてです。

今回のテーマは「psake」(日本の酒と同じ読み方)です。
psakeはPowerShellを使ったビルドツールです。
.NETの開発では、ビルドツールにMsBuildやNAntを利用することがありますが、psakeも同じ用途です。
では、さっそく。

1. psakeとは

psakeとは、PowerShellで書かれたビルドツールです。
アングルブラケット地獄に陥ることなく、PowerShellの機能をふんだんに使えるビルドスクリプトが書けます。
ソースコードと実行モジュールはGitHub上にホストされています。こちら。
NuGet経由で手に入れることも可能です。こちら。

2. 実際にビルドスクリプトを書いてみる

psakeで作るスクリプトは、タスクと、その依存関係を示すコードからなります。
例えばビルドをするスクリプト(タスクのことです)は以下のよう。

task Build{
    Write-Host -ForegroundColor Green "Building"
    exec { msbuild  Sample.csproj } "Error Building" | out-null
}

コンポーネントテストをするスクリプトは以下のよう。

task Test{
    Write-Host -ForegroundColor Green "Testing"
    exec { mstest /testcontainer:Sample.dll } "Error Testing" | out-null
}

そして、これらの実行順序を考慮して、依存関係を示すスクリプトがこんな感じ。

task Full -depends Build, Test

タスクに相当するものとして、一時領域のクリーンアップや、ビルド、コンポーネントテスト、メトリクス取得、テストカバレッジ取得、配置パッケージ作成、などなどが考えられるでしょうか。

3. ビルドしてみる

では、実際にビルドしてみます。
上述したコードをbuild.ps1に格納していると仮定します。

.\psake.ps1 -buildFile "build.ps1" -taskList "Full" -framework "4.0"

psakeの本体は、psake.psm1ですが、いちいちモジュールを読み込むのは面倒だということで
あらかじめヘルパーとして、psake.ps1が用意されています。
普段利用するときは、psake.ps1経由が良いと思います。
引数として渡しているものは、

-buildFile タスクが記述されているPSファイル
-taskList 実行するタスク
-buildFile ビルドに利用する.NET Frameworkのバージョン(何も指定しないと3.5でビルドされる)

です。

GitHubに、ASP.NET Webフォームのサンプルアプリをビルドスクリプトをセットにした、お試しpsakeセットを置きました。
こちらをご参照ください。

4. おわりに

気になるpsakeの採用実績(?)ですが、ちょっと調べました。

プロジェクト名 概要 URL
AutoMapper 規約ベースのマッピングツール https://github.com/AutoMapper/AutoMapper
Soma ORマッパー http://soma.codeplex.com/
Json.NET .NETのJSONフレームワーク http://json.codeplex.com/
Glimpse クライアントからサーバーサイドをデバックできるツール https://github.com/Glimpse/Glimpse

今は自分が担当するプロジェクトにて、psakeで書いたビルドスクリプトをJenkinsに実行させています。
他のビルドツールと比較し、PowerShellで書けるpsakeのほうが管理しやすいです。
PowerShellの恩恵を受けられるのはやはり大きいです。
(PowerShell自体の機能が多いですし、Windowsに標準で入ってきますし。)

今日はこんなところです。
明日は、@RyosukeUemotoさんにバトンタッチです。

AutoMapperを動かしてみる

0.前置き

仕事でAutoMapperを触る機会がありました。
覚書のために、その記録を残しておきます。

1.AutoMapperとは

規約ベースで利用するオブジェクト-オブジェクトマッパーです。
(A convention-based object-object mapper. )
英語の訳をそのまま。。。

DTOからEntityやViewModelにデータを詰め直す時に使います。
詰め替えるコードをえんえんと書かなくてもOKというわけです。例えば以下のようなコードがあるとします。

 // 変換元を
SrcEmployee srcEmployee = ...;

// 変換先に、詰め直す!
var destEmp = new DestEmployee
                {
                    Name = srcEmp.Name,
                    Age = Convert.ToInt32(srcEmp.Age),
                    Status = EmployeeStatusResolver(srcEmp.Status),
                    HireDate = CustomDateTimeConverter(srcEmp.Status)
                };

規約に従えって、AutoMapperを利用すればこんな感じになります。(もろもろ省いています)

Mapper.CreateMap<SrcEmployee, DestEmployee>();
var destEmp = Mapper.Map<SrcEmployee, DestEmployee>(srcEmp);

2.インストール

AutoMapperのインストールはnugetでできます。とても簡単。

3.実際に使ってみる

課題を作って、実際に変換処理を書いて見ます。

3-1.(課題)変換元と変換先のクラス

SrcEmployeeからDestEmployeeにデータの詰め替えを行います。
(プロパティ名の対応関係の規約は、説明が煩雑になりそうなので省きます。)

/// <summary>
/// 変換元のクラス
/// </summary>
public class SrcEmployee
{
    public string Name { get; set; }
    public string Age { get; set; }
    public string Status { get; set; }
    public DateTime HireDate { get; set; }
}

/// <summary>
/// 変換先のクラス
/// </summary>
public class DestEmployee
{
    public string Name { get; set; }
    public int Age { get; set; }
    public EmployeeStatus Status { get; set; }
    public string HireDate { get; set; }
}

この課題に対して、型変換や、値の変換等、変換ルールが必要なところをマッピング定義に書いていきます。

3-2.グローバルな変換規則を作る

どのマッピングでも使うような変換規則を作ります。
今回は主に2つ。

  • stringをintに変換:Convet.ToInt32()を利用
  • DateTimeをstringに変換:独自のコンバーターを利用

作った独自のコンバーターはこんな感じ。

public class CustomDateTimeConverter : TypeConverter<DateTime, string>
{
    protected override string ConvertCore(DateTime source)
    {
        return source.ToString("yyyy年MM月dd日");
    }
}

3-3.変換元のクラスと変換先のクラスに依存する変換規則を作る

今回の例ですと、Statusというプロパティになります。
stringから、enumのEmployeeStatusに変換しています。今度は独自のリゾルバーを作ります。

public class EmployeeStatusResolver : ValueResolver<SrcEmployee, EmployeeStatus>
{
    protected override EmployeeStatus ResolveCore(SrcEmployee source)
    {
        switch (source.Status)
        {
            case "在職":
                return EmployeeStatus.Stay;
            case "退職":
                return EmployeeStatus.Exit;
            case "長期休暇中":
                return EmployeeStatus.LongHoliday;
            default:
                throw new UnKnowonEmployeeStatusException();
        }
    }
}

3-4.変換定義をする

今まで考えた変換定義をコードにおこします。

// 2-2用のルール
Mapper.CreateMap<string, int>().ConvertUsing(Convert.ToInt32);
Mapper.CreateMap<DateTime, string>().ConvertUsing<CustomDateTimeConverter>();

// SrcEmployeeからDestEmployeeの変換定義と、2-3用のルール
Mapper.CreateMap<SrcEmployee, DestEmployee>()
    .ForMember(dest => dest.Status, opt => opt.ResolveUsing<EmployeeStatusResolver>());

3-5.マッピング

最後にマッピング!!これだけで、データの詰め直しが完了します。

var destEmp = Mapper.Map<SrcEmployee, DestEmployee>(srcEmp);

4.サンプルを書いてみての補足

最初にマッピングルールをいろいろ作らなきゃいけないのは面倒です。
ただかなりの確率で使いまわせることができるので、一回作ってしまえば良いです。

ASP.NET MVCで使うと便利だよ~って、マイコミジャーナルの記事でも言ってますので
興味のある方は、参考資料のほうをチェックしてみてください。

5.サンプルコード

サンプルコードはgithubにホスティングしてあります。
AutoMapperのサンプル
コード本体
※実は、初github!

6.参考資料

本家のページは以下です。CodePlexや、Google Groupsや、githubに情報が散らばってますけど、とりあえずここから行けばよし。
AutoMapperの本家のページ
マイコミジャーナルにも記事があったので載せておきます。
AutoMapperでオブジェクト間のデータコピーを行う

All-In-One Code Framework

ネットサーフィンしていたら面白い記事を見つけました。

Microsoft、コードサンプル集「All-In-One Code Framework」を紹介

24種類のMS技術、300種類のコードサンプルを提供しているようです。
CodePlexのサイトはこちら。
Microsoft All-In-One Code Framework

ただ300種類もサンプルがあると、探すのが大変でしょうということで
Microsoft All-In-One Code Framework “Sample Browser” v2 available for Technical Preview
という専用ブラウザーをコミュニティーで開発中らしいです。

今後のためにもいづれ利用方法を把握しておきたいです。