C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2007/07/31 12:36
ビルド自動化のために。
PowerShell で Sandcastle プロジェクトをビルドする関数。
厳密には、Sandcastle Help File Builder のプロジェクト ( 拡張子 .shfb ) をビルドする。
この関数は内部で Invoke-Process 関数を使用する。

[ パラメータ ]
sandcastleProjectFilePath
Sandcastle Help File Builder のプロジェクトファイルのパス。

[ 戻り値 ]
戻り値については Invoke-Process 関数を参照。

[ Build-SandcastleProject 関数 ]
function global:Build-SandcastleProject
{
    param ([string] $sandcastleProjectFilePath)
    trap { break; }

    if ([String]::IsNullOrEmpty($sandcastleProjectFilePath)) { throw "引数 sandcastleProjectFilePath が null または空の文字列です。"; }

    $sandcastleBuilderConsolePath = "$Env:ProgramFiles\EWSoftware\Sandcastle Help File Builder\SandcastleBuilderConsole.exe";
    $sandcastleBuilderConsoleArgs = "`"$sandcastleProjectFilePath`"";
   
    return Invoke-Process $sandcastleBuilderConsolePath $sandcastleBuilderConsoleArgs;
}



[ 使用例 ]
$result = Build-SandcastleProject "C:\work\Solution1\Reference\Solution1.shfb";
Write-Host $result.Message;
if (!$result.IsSuccess)
{
    Write-Host "Sandcastle プロジェクトのビルドに失敗しました。" -ForegroundColor "Red";
}





【 ダウンロード 】
自作の PowerShell 関数は、以下の記事からまとめてダウンロードできます。

YokoKen.PowerShell.Scripts
2007/07/30 23:27
ビルド自動化のために。
PowerShell で Visual Studio のソリューションから Visual SourceSafe の関連付けを削除する関数。
この関数が行うことは以下の3つ
  • 指定したフォルダ内の全てのファイル・フォルダから、"読み取り専用" 属性を外す
  • mssccprj.scc 等の VSS ファイルを全て削除
  • ソリューションファイル, プロジェクトファイル ( ※ ) に記述されている VSS の設定を削除
※ C# プロジェクト, VB プロジェクト, Web 配置プロジェクト, セットアッププロジェクトに対応。


[ パラメータ ]
solutionFolderPath
ソリューションが格納されているフォルダのパス。

[ Delete-VssRelation 関数 ]
function Delete-VssRelation
{
  param ([string] $solutionFolderPath)
 
  $solutionAllContents = Get-ChildItem $solutionFolderPath -recurse -force;
 
  # 全てのコンテンツから読み取り専用属性を削除
  foreach ($content in $solutionAllContents)
  {
    $contentAttributes = [System.IO.File]::GetAttributes($content.FullName);
    $newContentAttributes = $contentAttributes -band (-bnot[System.IO.FileAttributes]::ReadOnly);
    [System.IO.File]::SetAttributes($content.FullName, $newContentAttributes);
  }
 
  # VSS関連ファイルの削除
  $vssFiles = $solutionAllContents | Where-Object{ ($_.Name -like "*.scc") -or ($_.Name -like "*.vssscc") -or($_.Name -like "*.vsscc") -or ($_.Name -like "*.vspscc"); };
  if ($() -ne $vssFiles)
  {
    $vssFiles | Remove-Item -force;
  }
 
  # ソリューションファイルからVSS関連付けの記述を削除
  $slnFiles = $solutionAllContents | Where-Object { $_.Name -like "*.sln"; };
  if ($() -ne $slnFiles)
  {
    foreach ($slnFile in $slnFiles)
    {
      $slnFilePath = $slnFile.FullName;
      $slnFileContents = [System.IO.File]::ReadAllText($slnFilePath, [System.Text.Encoding]::UTF8);
      $newSlnFileContents = $slnFileContents -replace @("([ \t]*?GlobalSection\(SourceCodeControl\)(.|\r|\n)*?EndGlobalSection\r?\n|[ \t]*?Scc.*?\r?\n)", "");
      [System.IO.File]::WriteAllText($slnFilePath, $newSlnFileContents, [System.Text.Encoding]::UTF8);
    }
  }
 
  # プロジェクトファイル ( C# or VB or Web Deployment ) からVSS関連付けの記述を削除
  $projFiles = $solutionAllContents | Where-Object { ($_.Name -like "*.csproj") -or ($_.Name -like "*.vbproj") -or ($_.Name -like "*.wdproj"); };
  if ($() -ne $projFiles)
  {
    foreach ($projFile in $projFiles)
    {
      $projFilePath = $projFile.FullName;
      $projFileContents = [System.IO.File]::ReadAllText($projFilePath, [System.Text.Encoding]::UTF8);
      $newProjFileContents = $projFileContents -replace @("[ \t]*?<Scc.*?>[^<]*?</Scc.*?>\r?\n", "");
      [System.IO.File]::WriteAllText($projFilePath, $newProjFileContents, [System.Text.Encoding]::UTF8);
    }
  }
 
  # プロジェクトファイル ( Setup ) からVSS関連付けの記述を削除
  $vdprojFiles = $solutionAllContents | Where-Object { $_.Name -like "*.vdproj"; };
  if ($() -ne $vdprojFiles)
  {
    foreach ($vdprojFile in $vdprojFiles)
    {
      $vdprojFilePath = $vdprojFile.FullName;
      $vdprojFileContents = [System.IO.File]::ReadAllText($vdprojFilePath, [System.Text.Encoding]::UTF8);
      $newVdprojFileContents = $vdprojFileContents -replace @("[ \t]*?`"Scc.*?`".*?\r?\n", "");
      [System.IO.File]::WriteAllText($vdprojFilePath, $newVdprojFileContents, [System.Text.Encoding]::UTF8);
    }
  }
 
  trap
  {
    break;
  }
}



[ 使用例 ]
Delete-VssRelation "C:\work\Solution1";



# 自分用に適当に作ったのであしからず。


【 ダウンロード 】
自作の PowerShell 関数は、以下の記事からまとめてダウンロードできます。

YokoKen.PowerShell.Scripts
2007/07/28 20:25
PowerShell の例外処理は VB6 のような非構造化例外処理を採用している。
PowerShell では trap ブロックによって例外を捕捉する。
この例外処理の動作がけっこうややこしい ( 特に $ErrorActionPreference が関わってくる条件 ) ので、検証してまとめてみた。 ( 掲載したサンプルコードはそのまま実行可能。 )


[ throw ステートメント ]
PowerShell では、 throw ステートメントを使用して例外を明示的にスローすることができる。スローできるのは Exception 派生クラスのインスタンス、ErrorRecord クラス (System.Management.Automation) のインスタンス、文字列である。これ以外のオブジェクトをスローしようとした場合、ToString メソッドによって文字列に変換されてスローされる。
なお、文字列がスローされた場合は、その文字列を元に RuntimeException クラス (System.Management.Automation) のインスタンスが生成され、この RuntimeException がスローされる。


[ trap ブロック ]
trap ステートメントの直後に例外の型を指定しておくと、その型の例外のみハンドルされる。(型指定は省略可。)
trap ブロックは一つのスコープに対して複数用意することができるが、実際に有効になるのはその中の一つだけであり、先に定義された trap ブロックが使用される。trap ブロックはスコープ内のどこに配置してもよく、同一スコープ内の全ての処理に作用する。
例えば、以下のコードでは、どこで例外が発生しても、"aaa" と出力される。

function Sample1
{
  param ([Int32] $arg0)
 
  if ($arg0 -eq 1) { throw "いち"; }
  trap { "aaa"; }
  if ($arg0 -eq 2) { throw "に"; }
  trap { "bbb"; }
  if ($arg0 -eq 3) { throw "さん"; }
  trap { "ccc"; }
}

Sample1 1;
Sample1 2;
Sample1 3;



[ 捕捉した例外を取得 ]
trap ブロック内では &_ 変数にて、捕捉した例外にアクセスできる。ただし、$_ 変数に格納されているのは ErrorRecord オブジェクトであり、実際に発生した例外は ErrorRecord の Exception プロパティから取得する。つまり、 $_.Exception にて実際に発生した例外を取得できる。
例外を捕捉して新しく別の例外としてスローする例を以下に示す。

function Sample2
{
  throw (New-Object "System.ArgumentException");
  trap [System.ArgumentException]
  {
    $ex = $_.Exception;
    throw (New-Object "System.IO.FileNotFoundException" @("ファイルが見つからないよ", $ex));
  }
}

Sample2;



[ 例外の処理方法 ]
例外が発生すると、その例外を捕捉できる trap ブロックが同一スコープ内に存在するかどうか探される。存在した場合は、その trap ブロックに制御が移り、存在しない場合は上位スコープに例外がスローされる。
例外が上位スコープにスローされると、上位スコープで再び trap ブロックが存在するかどうか探される。これを繰り返し、最上位のスコープまで trap ブロックが存在しなかった場合、処理は中断され、例外がユーザーに通知される。


[ tarp ブロック用のステートメント ]
trap ブロック内では、以下の2つのステートメントを使用できる。

break ステートメント
スコープを抜ける。例外は上位に再スローする。

continue ステートメント
例外が発生したコードの次のコードに制御を移す。例外は握りつぶされる。


[ continue ステートメントについて ]
continue ステートメントが実行されると例外が発生したコードの次のコードに制御が移動すると書いたが、厳密には、「同一スコープ内での次のコードに制御を移動」となる。
以下のようなコードを例に挙げてみる。

function Sample3
{
  &{
    "ほげ";
    throw "throw1";
    "Hoge";
  };
  &{
    "ふが";
    throw "throw2";
    "Fuga";
  };
  trap
  {
    continue;
  }
}

Sample3


この Sample3 関数内には、trap ブロックを除いて2つのブロックが存在し、この2つのブロックの中には trap ブロックが含まれていない。
このコードを実行すると、まず1つ目のブロックで "ほげ" と出力した後例外が発生する。一つ目のブロック内には trap ブロックが存在しないので、例外は上位にスローされる。その結果、一つ上位のスコープにある trap ブロックによって例外がハンドルされる。trap ブロック内には continue ステートメントが記述されているので、処理を続行することになる。遷移先は「同一スコープ内での次のコード」なので、1つ目のブロック内の処理は中断され、2つ目のブロックに制御が移る。2つ目のブロックでも同様の動作が繰り返される。
結果として、以下の出力が得られる。

ほげ
ふが


[ $ErrorActionPreference 変数 ]
trap ブロック内で break ステートメントも continue ステートメントも実行されなかった場合、$ErrorActionPreference 変数の設定に従った動作が行われる。
ただし、trap ブロック内で新たに例外が発生した場合は除く。 ( 例えば捕捉した例外を元に新しく例外を生成してスローした場合等。 )
また、捕捉できる trap ブロックがどこにもない例外が発生した場合 ( 2007/11/13 追記:throw ステートメントでスローした例外は除く ) も、$ErrorActionPreference 変数の設定に従った動作が行われるが、一度でも trap ブロックに捕捉された例外に対しては動作しない。

$ErrorActionPreference 変数には ActionPreference 列挙体 ( System.Management.Automation ) の列挙値を設定できる。ActionPreference 列挙体には以下の4つの列挙値が用意されている。

SilentlyContinue ( サイレント続行 )
例外が発生したコードの次のコードに制御を移す。例外は握りつぶされる。
trap ブロック内で continue ステートメントが実行された場合と同様の挙動。

Stop ( 中断 )
スコープを抜ける。例外は上位に再スローする。
trap ブロック内で break ステートメントが実行された場合と同様の挙動。

Continue ( 続行 )
例外が発生したコードの次のコードに制御を移す。例外はユーザーに通知される。( 再スローされるわけではない。 )
この値が既定の設定。

Inquire ( 問い合わせ )
例外のメッセージを表示し、動作をユーザーに問い合わせる。選択できる動作は、続行, サイレント続行, 中断, 中断 ( 例外握りつぶし ) の4つ。


・trap ブロック内で break ステートメントも continue ステートメントも実行されなかった場合の例
trap ブロック内で break ステートメントも continue ステートメントも実行されなかった場合の例を以下に示す。

function Sample4
{
  &{
    throw (New-Object "System.InvalidOperationException" @());
    "ほげ";
    trap
    {
      "trap1";
    }
  };
  "ふが";
  trap
  {
    "trap2";
    break;
  }
}

$ErrorActionPreference = "SilentlyContinue";
Sample4;


このコードを実行すると、以下の出力が得られる。

trap1
ほげ
ふが

Sample4 関数内のスクリプトブロックは一行目で例外をスローしている。この例外を捕捉する trap ブロックが同一スコープ内にあるので、この trap ブロックに制御が移動する。しかし、break ステートメントも continue ステートメントも記述されていないので、trap ブロックを抜けた後は $ErrorActionPreference 変数に従った動作が行われる。
$ErrorActionPreference 変数には "SilentlyContinue" を設定しているので、例外は握りつぶされ、次の行の "ほげ" という文字列が出力され、続いて "ふが" という文字列が出力される。

"trap2" は出力されないことに注意する。trap ブロック内で break 及び continue が実行されなかった場合、その上位に trap ブロックがあろうがなかろうが、$ErrorActionPreference 変数に従った動作が行われる。その結果例外が握りつぶされたため、2つ目の trap ブロックは実行されていない。


・捕捉できる trap ブロックがどこにもない例外が発生した場合の例
捕捉できる trap ブロックがどこにもない例外が発生した場合の例を以下に示す。

function Sample5
{
  &{
    throw (New-Object "System.InvalidOperationException" @());
    "ほげ";
  };
  "ふが";
}

$ErrorActionPreference = "SilentlyContinue";
Sample5;


このコードを実行すると、以下の出力が得られる。

ほげ
ふが

Sample5 関数内のスクリプトブロックは一行目で例外をスローしている。この例外を捕捉する trap ブロックが、同一スコープ内にも上位スコープ内にも存在しないため、$ErrorActionPreference 変数に従った動作が行われる。
$ErrorActionPreference 変数には "SilentlyContinue" を設定しているので、例外は握りつぶされ、次の行の "ほげ" という文字列が出力され、続いて "ふが" という文字列が出力される。


[ テクニック ]
適当に考えた、テクニックというほどでもないテクニックを3つほど。
「もっとエレガントに書けるだろ!」って方は是非コメントでお教えください m( _ _ )m

try もどき
trap ブロックは配置されているスコープ内の全てに対して有効である。C# の try ブロック のように範囲を限定する特別な機能は備わっていない。
C# の try ブロック のように範囲を限定したい場合は以下のようなテクニックが使える。

function Technique1
{
  param ([int] $arg0)
  &{
    if ($arg0 -eq 1)
    {
      throw (New-Object "System.ArgumentException" @());
    }
    trap [System.ArgumentException]
    {
      "1つ目のブロックで発生した例外を捕捉";
      break;
    }
  };

  &{
    if ($arg0 -eq 2)
    {
      throw (New-Object "System.ArgumentException" @());
    }
    trap [System.ArgumentException]
    {
      "2つ目のブロックで発生した例外を捕捉";
      break;
    }
  };
}

Technique1 1;
Technique1 2;


つまり、trap ブロックが有効となる範囲を狭めるために、スクリプトブロックを作成し、& を使ってその場で実行させるということ。


catch ( 例外握りつぶし ) もどき
PowerShell では trap ブロックが C# の catch ブロックに相当するが、catch ブロックで例外を握りつぶすような機能が用意されていない。 ( continue ステートメントを使えば例外を握りつぶしせるが、そのまま次のコードに復帰してしまう。 )
C# の catch ブロックで例外を握りつぶすような感じの処理を行いたい場合は以下のようなテクニックが使える。

function Technique2
{
  &{
    &{
      "この次に例外が発生";
      throw "hoge";
      "例外は握りつぶされるが、ここは出力されない";
    };
    trap
    {
      continue;
    }
  };
  "例外が握りつぶされ、このコードが実行される";
}

Technique2


つまり、trap ブロックが置かれているスコープ内に、スクリプトブロックを一つだけ配置し、continue ステートメントによって例外を握りつぶす。こうすることによって、trap ブロックが一つ上位に配置されているため、スクリプトブロックの中の処理は中断される。


finally もどき
PowerShell には C# の finally ブロックのように確実な後処理を行うための特別な機能が用意されていない。
C# の finally ブロック のように範囲を限定したい場合は以下のようなテクニックが使える。

function Technique3
{
  param ([Boolean] $arg0)
 
  $finallyBlock =
    {
      "確実な後処理";
    };

  if ($arg0)
  {
    throw "すろー";
  }
  &$finallyBlock;

  trap
  {
    &$finallyBlock;
    break;
  }
}

Technique3 $False;
Technique3 $True;


つまり、確実な後処理をスクリプトブロックとして変数に格納しておき、正常終了時も、例外捕捉時もそれを呼び出すということ。

try - catch - finally もどき
これらを状況に応じてうまく組み合わせれば try - catch -finally が完全に再現できる。 ( でも可読性はあまりよくない。。。 )
まぁ、「catch ( 例外握りつぶし ) もどき」はあまり使うことないかな。


# 追記 ( 2007/11/07 )

C# の try -catch - finally に近い形式で記述する方法を記事にしました。

# 追記ここまで


[ 最後に ]
PowerShell の例外処理はこんなところかな。
ん、$Error 変数?なんのことやら。


# 追記 ( 2007/11/14 )

例外処理には、まだ他にも書くべきことがありました。 → エラーパイプライン

# 追記ここまで
2007/07/26 15:55
ビルド自動化のために。
PowerShell で Visual Studio のソリューションをリビルドするための関数。
ソリューションにセットアッププロジェクトが含まれている場合は注意が必要(後述)。
この関数は内部で Invoke-Process 関数を使用する。

[ パラメータ ]
solutionPath
ソリューションファイルのパス。

vsVersion
Visual Studio のバージョン。

timeoutMilliseconds
プロセスの実行時間に対するタイムアウト値 (単位:ミリ秒)。
無制限に待機する場合、-1 または Int32.MaxValue を指定。
省略した場合は -1。


[ 戻り値 ]
戻り値については Invoke-Process 関数を参照。


[ Rebuild-Solution 関数 ]
function global:Rebuild-Solution
{
    Param([String]$solutionPath, [string]$vsVersion, [int]$timeoutMilliseconds = [System.Threading.Timeout]::Infinite)
    trap { break; }
   
    if ([String]::IsNullOrEmpty($solutionPath)) { throw "引数 solutionPath が null または空の文字列です。"; }
    if ([String]::IsNullOrEmpty($vsVersion)) { throw "引数 vsVersion が null または空の文字列です。"; }
   
    $vsFolderName = $();
    if (@("9.0", "9", "2008") -contains $vsVersion)
    {
        $vsFolderName = "Microsoft Visual Studio 9.0";
    }
    elseif (@("8.0", "8", "2005") -contains $vsVersion)
    {
        $vsFolderName = "Microsoft Visual Studio 8";
    }
    elseif (@("7.1", "2003") -contains $vsVersion)
    {
        $vsFolderName = "Microsoft Visual Studio .NET 2003";
    }
    else
    {
        $vsFolderName = "Microsoft Visual Studio $vsVersion";
    }
    $devenvPath = "$Env:ProgramFiles\$vsFolderName\Common7\IDE\devenv.com"
    $devenvArgs = "/rebuild Release `"$solutionPath`"";
   
    return Invoke-Process $devenvPath $devenvArgs $timeoutMilliseconds;
}



[ 使用例 ]
$result = Rebuild-Solution "C:\work\Hoge\Hoge.sln" "9.0";
Write-Host $result.Message;
if (!$result.IsSuccess)
{
    Write-Host "ソリューションのリビルドに失敗しました。" -ForegroundColor "Red";
}



[ セットアッププロジェクトについて ]
既定ではソリューションのビルドを行ってもセットアッププロジェクトはビルドされない。
以下の手順を行うことで、Releaseビルド時にセットアップ プロジェクトもビルドされるよう設定できる。
  1. ソリューションエクスプローラでソリューションを選択する。
  2. [ ビルド ] - [ 構成マネージャ ] にて構成マネージャウィンドウを開く。
  3. [ アクティブ ソリューション構成 ] を "Release" に設定する。
  4. セットアッププロジェクトの [ ビルド ] 列にチェックを付ける。
  5. [ 閉じる ] ボタンをクリックして完了する。


[ 関連リンク ]
Devenv コマンド ライン スイッチ


【 ダウンロード 】
自作の PowerShell 関数は、以下の記事からまとめてダウンロードできます。

YokoKen.PowerShell.Scripts
2007/07/25 17:55
ビルド自動化のために。
PowerShell で Visual SourceSafe から最新のソースを取得するための関数。
VSSFLAG_RECURSYES フラグにより、プロジェクトツリー内のサブプロジェクトは再帰的に取得される。

[ パラメータ ]
sourcePathInVss
VSS 上のソースのパス ( ファイルまたはフォルダ )。

vssIniFilePath
srcsafe.ini ファイルのパス。

localPath
取得したソースを保存するローカルパス。
省略した場合、VSS で設定した作業フォルダに保存される。

loginUserName
ログインするユーザー名。
省略した場合、現在のユーザー名が使用される。

loginUserPassword
ログインするユーザーのパスワード。
省略した場合、空の文字列が使用される。


[ Get-LatestSource関数 ]
function Get-LatestSource
{
  Param([string] $sourcePathInVss, [string] $vssIniFilePath, [string] $localPath, [string] $loginUserName, [string] $loginUserPassword)
 
  $finallyBlock =
    {
      $vssDatabase.Close();
      [System.Runtime.InteropServices.Marshal]::ReleaseComObject($vssItem) | Out-Null;
      [System.Runtime.InteropServices.Marshal]::ReleaseComObject($vssDatabase) | Out-Null;
      trap { continue; }
    };
 
  [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualStudio.SourceSafe.Interop") | Out-Null;
  $vssDatabase = New-Object "Microsoft.VisualStudio.SourceSafe.Interop.VSSDatabaseClass" @();
  $vssDatabase.Open($vssIniFilePath, $loginUserName, $loginUserPassword);
 
  $vssItem = $vssDatabase.get_VSSItem($sourcePathInVss, $False);
  $flag = [Microsoft.VisualStudio.SourceSafe.Interop.VssFlags]::VSSFLAG_RECURSYES;
  $vssItem.Get([ref]$localPath, $flag);
 
  &$finallyBlock;
 
  trap
  {
    &$finallyBlock;
    break;
  }
}



[ 使用例 ]
Get-LatestSource "$/Hoge.root" "\\YokoKen\VSS\srcsafe.ini";



# 自分用に適当に作ったのであしからず。


[ ソース変更履歴 ]
2007/07/26

・第一パラメータに、VSS上でのパスを複数指定するのではなく、単一のパスを指定するように変更。
・第三パラメータを追加し、ソースを保存するローカルパスを指定できるように変更。
・COM オブジェクトの解放処理を追加。

2007/07/27
・$ErrorActionPreference 変数が "Stop" に設定された環境だと後処理が行われない可能性があったので、確実に行われるように修正。


【 ダウンロード 】
自作の PowerShell 関数は、以下の記事からまとめてダウンロードできます。

YokoKen.PowerShell.Scripts
2007/07/22 16:11
コマンドレットのコンストラクタ辺りで、Debugger クラス (System.Diagnostics)Launch メソッド を呼び出せばいいだけです。
PowerShell でコマンドレットを呼び出すとデバッガ選択ウィンドウが出てきますので、コマンドレットのプロジェクトを開いている Visual Studio を選択してあげてください。

他にも、Visual Studio の [ デバッグ ] - [ プロセスにアタッチ] にて、PowerShell に直接アタッチすることでも、デバッグ可能になります。

どちらにしろ、PowerShell にインストールしたスナップイン DLL が配置されているディレクトリに  .pdb ファイルを配置することと、ソースコードにブレークポイントを貼ることを忘れずに。


# PowerShell に限らず、他者が開発したアプリケーションにホストされるアセンブリをデバッグする際に有効な方法です。例えば、インストーラのカスタム動作のデバッグもこの方法で行います。
2007/07/21 21:55
テスト駆動とかXPとかアジャイルとか、興味はあるけどまだ実践したことはありません。
顧客常駐なんて、ウチじゃさすがに無理だと思いますが、テスト駆動は取り入れようと思えば取り入れられると睨んでます。

.NET開発ならNUnitとかNMockとかTestDriven.NETとかを使用する、ということくらいは知ってますが、インストールしたっきり全然使ってなかったりします^^;
で、次の案件ではテスト駆動開発を取り入れようと密かに企んでいたのですが、craftsmanさん
オブジェクト思考: テスト駆動開発やユニットテストを定着させるには という記事を読んで、僕はテスト駆動開発についてのしっかりとした知識を持っておらず、とても危険だったということを思い知らされました。
だって、「構成管理システムによってテスト実行を自動化させる」 なんて事、全く知らなかったんです。普通に手動でNUnitを実行させればいいとばかり思ってました。
こりゃ、取り入れる前にしっかり勉強しとかないと。。。せっかく新しいことをやっても、知識不足のせいで失敗に終わったら台無しですからね。
2007/07/17 23:38
AさんとBさんの会話が聞こえてきました。

Aさん「ここがエラーになるんだけどなんでかわかる?」
Bさん「うーん・・・」
Aさん「よこけんにも聞いたけどわからなかったんだよ」
Bさん「・・・あ、ここが悪いんじゃないですか?ここを○○に変えれば・・・」
Aさん「ここかぁ?・・・おおっホントだ!ありがとう助かったよ。さすがだな!」


聞き耳立ててたら、どうもイベントハンドラの書き方で躓いていた模様。
僕に聞いてもわからなかった問題は、Bさんの手によって無事解決したようです。
さすがです、Bさん。












・・・って、そんな質問された覚えないのですが ('A`;)



たぶん、AさんはCさんにも先週末に同じ質問してたから、それがいつの間にか勘違いで僕に質問したことになったのでしょう。そういや、その日は僕もAさんから別の質問を受けました。 ( ちゃんと解決しましたけど。 )


なんだ、このやるせなさは。。。 orz
まぁ別にいいんですけどね。むしろ、これブログのネタになるんじゃね?とか考えてたしw
タグ:
2007/07/14 11:33
MSDN マガジン 8月号に、Juval Lowy 氏の「宣言型の WCF セキュリティ」 という記事が掲載されています。
この記事では、以下の5つのシナリオで適用すべきセキュリティについての解説と、それを容易に適用できるように Juval Lowy 氏が作成した、「セキュリティ フレームワーク」 についての解説が記述されています。
  • イントラネット アプリケーション
  • インターネット アプリケーション
  • 企業間アプリケーション
  • 匿名アプリケーション
  • セキュリティなし

Juval Lowy 氏が作成した 「セキュリティ フレームワーク」 は、ソースコード及びサンプルコードのセットでダウンロードできます。

基礎: 宣言型の WCF セキュリティ -- MSDN Magazine, August 2007
セキュリティ フレームワーク 及び サンプルコードのダウンロード

タグ: .NET C# WCF
2007/07/09 00:28
こんなクラスがあったんだ。。。

MemoryFailPoint クラス (System.Runtime)

MSDN より抜粋

MemoryFailPoint クラスのインスタンスを作成すると、メモリ ゲートが作成されます。メモリ ゲートとは、大量のメモリを必要とするアクティビティを開始する前に、十分なリソースがあるかどうかをチェックすることです。チェックに合格しなかった場合、操作を開始できないようにする InsufficientMemoryException がスローされるため、リソース不足が原因となってアプリケーションが実行中に失敗する可能性が減少します。これにより、アプリケーションでは、パフォーマンスを低下させ、OutOfMemoryException や、コード内の任意の場所で OutOfMemoryException を誤って処理したことが原因で発生する状態の破損を避けることができます。


つまり、OutOfMemoryException という、ある意味天災的な例外を、事前に察知するためのクラスです。
処理を開始する前にこれを察知できるというのは、場合によっては大きなメリットとなりそうです。
ただし、MemoryFailPoint が InsufficientMemoryException をスローしなかった場合でも、メモリは論理的には確保されていますが物理的に確保されているわけではありません。従って、 OutOfMemoryException がスローされる可能性も残っているということです。

このクラス自体の使い方は簡単です。
コンストラクタ でメモリーサイズ ( 単位はMB ) を指定します。指定したサイズのメモリーが使用できない場合は、InsufficientMemoryException クラス (System) がコンストラクタからスローされます。
なお、使用後は必ず Dispose メソッド を呼び出す必要があることに注意します。 ( InsufficientMemoryException が発生したら呼べないけど、コンストラクタが例外投げた場合、CLR は即座にファイナライザを呼び出すから問題無し。 → 勘違いでした。CLR は即座にファイナライザを呼び出したりはしません。でも、例外が発生したらリソース確保もされないと思います。 )
ちなみに、InsufficientMemoryException は OutOfMemoryException の派生クラスです。


[ 参考 ]
プログラミング Microsoft .NET Framework 第2版
タグ: .NET C# メモリ