C#と諸々

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

2008/04/03 01:27
ビルド自動化のために。
NUnit を使用して記述されたユニットテストを実行する関数。
この関数は内部で Invoke-Process 関数を使用する。


[ パラメータ ]
testAssemblyPaths
 ユニットテストアセンブリのパスの配列。

xmlOutputDirectoryPath
XML 出力ファイルの出力先ディレクトリのパス。

version
NUnit のバージョン。

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


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


[ Invoke-NUnit ]
function global:Invoke-NUnit
{
    param ([string[]] $testAssemblyPaths, [string]$xmlOutputDirectoryPath, [string]$version, [int]$timeoutMilliseconds = [System.Threading.Timeout]::Infinite)
    trap { break; }
   
    if ("$testAssemblyPaths".Length -eq 0) { throw "引数 testAssemblyPaths が null または空の配列です。"; }
    if ([string]::IsNullOrEmpty($xmlOutputDirectoryPath)) { throw "引数 xmlOutputDirectoryPath が null または空の文字列です。"; }
    if ([string]::IsNullOrEmpty($version)) { throw "引数 version が null または空の文字列です。"; }
   
    $testAssemblyPathsText = [string]::Empty;
    $testAssemblyPaths | % { $testAssemblyPathsText += "`"$_`" "; };
   
    $nunitConsolePath = "$Env:ProgramFiles\NUnit $version\bin\nunit-console.exe";
    $nunitConsoleArgs = "$testAssemblyPathsText /xml=`"$xmlOutputDirectoryPath\TestResult.xml`" /nologo /nodots";
   
    return Invoke-Process $nunitConsolePath $nunitConsoleArgs $timeoutMilliseconds;
}



[ 使用例 ]
$testAssemblyPaths =
    @(
        "C:\work\Hoge\Project1.Test\bin\Release\Project1.Test.dll",
        "C:\work\Hoge\Project2.Test\bin\Release\Project2.Test.dll"
    );
$xmlOutputDirectoryPath = "C:\work\Hoge";
$result = Invoke-NUnit $testAssemblyPaths $xmlOutputDirectoryPath "2.4.6";
if (!$result.IsSuccess)
{
    Write-Host "ユニットテストが失敗しました。" -ForegroundColor "Red";
}





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

YokoKen.PowerShell.Scripts
スポンサーサイト



2008/04/03 00:55
ビルド自動化のために。
PowerShell でプロセスを実行する関数。


[ パラメータ ]
processPath
プロセス (実行可能ファイル) のパス。

processArgs
プロセスを実行する際に渡す引数。
省略可能。

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


[ 戻り値 ]
プロセスの実行結果に関する情報を格納するハッシュテーブル。
各キーの説明を以下に記述する。

IsSuccess
プロセスが正常終了した場合は true、それ以外の場合は false。
プロセスが正常終了したかどうかは、プロセスの終了コードを元に判断される。

IsComplete
プロセスがタイムアウトせずに完了した場合は true、それ以外の場合は false。

Message
プロセスが実行中に出力したメッセージ。

ErrorMessage
プロセスが実行中に出力したエラーメッセージ。


[ Invoke-Process 関数 ]
function global:Invoke-Process
{
    param ([string] $processPath, [string]$processArgs, [int]$timeoutMilliseconds = [System.Threading.Timeout]::Infinite)
    trap
    {
        if ($() -ne $process)
        {
            $process.Dispose();
        }
        break;
    }
   
    if ([String]::IsNullOrEmpty($processPath)) { throw "引数 processPath が null または空の文字列です。"; }
   
    $process = New-Object "System.Diagnostics.Process";
    $process.StartInfo = New-Object "System.Diagnostics.ProcessStartInfo" @($processPath, $processArgs);
    $process.StartInfo.WorkingDirectory = (Get-Location).Path;
    $process.StartInfo.RedirectStandardOutput = $True;
    $process.StartInfo.RedirectStandardError = $True;
    $process.StartInfo.UseShellExecute = $False;
    $process.Start() | Out-Null;
   
    $message = $process.StandardOutput.ReadToEnd();
    $errorMessage = $process.StandardError.ReadToEnd();
    $complete = $process.WaitForExit($timeoutMilliseconds);
    if (!$complete)
    {
        $process.Kill();
    }
   
    $result =
        @{
            "IsSuccess" = ($process.ExitCode -eq 0);
            "IsComplete" = $complete;
            "Message" = $message;
            "ErrorMessage" = $errorMessage;
        };
    $process.Dispose();
   
    return $result;
}



[ 使用例 ]
$result = Invoke-Process "$Env:ProgramFiles\Microsoft Visual Studio 9.0\Common7\IDE\devenv.com" "/rebuild Release `"C:\work\Hoge\Hoge.sln`"";
Write-Host $result.Message;
if (!$result.IsSuccess)
{
    Write-Host "ソリューションのリビルドに失敗しました。" -ForegroundColor "Red";
}





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

YokoKen.PowerShell.Scripts
2007/10/21 18:27

ZipPackage (.net framework 3.0, System.IO.Package) - いろいろ備忘録日記

.NET Framework 3.0 から、新しく ZipPackage クラス (System.IO.Packaging) が追加されたそうです。このクラスを使用することで、Zip アーカイブを生成することができます。
( ただし、このクラスの目的は Open Packaging Conventions (OPC) によるパッケージ化であるため、ZIP アーカイブ内に "[Content_Types].xml" というファイルが必ず含まれてしまうようです。 )

このクラスを使用して、Zip アーカイブを生成する PowerShell 関数を書いてみました。


[ パラメータ ]
sourcePath
対象ファイルまたは対象ディレクトリのパス。


[ 戻り値 ]
Zip アーカイブのバイナリデータを表す byte 配列。


[ Create-ZipArchive 関数 ]
function Create-ZipArchive
{
  param([string]$sourcePath)
 
  [System.Reflection.Assembly]::LoadWithPartialName("WindowsBase") | Out-Null;
 
  $source = Get-Item $sourcePath;
  $sourceFiles =
    &{
      if ($source -is [System.IO.FileInfo])
      {
        return @($source);
      }
      elseif ($source -is [System.IO.DirectoryInfo])
      {
        return $source.GetFiles("*", "AllDirectories");
      }
      else
      {
        throw (New-Object "System.IO.FileNotFoundException" @($sourcePath));
      }
    };
 
  $packageStream = New-Object "System.IO.MemoryStream";
  $package = [System.IO.Packaging.Package]::Open($packageStream, "CreateNew");
 
  $baseUri = New-Object "System.Uri" @($sourcePath);
  foreach ($sourceFile in $sourceFiles)
  {
    $sourceFileUri = New-Object "System.Uri" @($sourceFile.FullName);
    $sourceFileRelativeUri = $baseUri.MakeRelativeUri($sourceFileUri);
    $partUri = [System.IO.Packaging.PackUriHelper]::CreatePartUri($sourceFileRelativeUri);
    $part = $package.CreatePart($partUri, "", "Maximum");
    $sourceFileData = [System.IO.File]::ReadAllBytes($sourceFile.FullName);
    $partStream = $part.GetStream();
    $partStream.Write($sourceFileData, 0, $sourceFileData.Length);
  }
 
  $package.Close();
  $result = $packageStream.ToArray();
  $packageStream.Dispose();
 
  return $result;
 
  trap
  {
    if ($() -ne $package)
    {
      $package.Close();
    }
    if ($() -ne $packageStream)
    {
      $packageStream.Dispose();
    }
  }
}



[ 使用例 ]
$zipData = Create-ZipArchive "C:\Work\Directory1";
[System.IO.File]::WriteAllBytes("C:\Work\Directory1.zip", $zipData);



[ 補足 ]
ZipPackage クラスは、コンストラクタを公開していません。代わりに、Package クラス (System.IO.Packaging)Open メソッド を使用して ZipPackage クラスのインスタンスを取得します。


[ 参考 ]
System.IO.Packaging 名前空間
OPC: データのパッケージ化のための新しい標準 -- MSDN Magazine, August 2007


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

YokoKen.PowerShell.Scripts
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/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