orangain flavor

じっくりコトコト煮込んだみかん2。知らないことを知りたい。

Visual Studioでビルド後にZIPアーカイブを手軽に作る

はじめに

Visual Studioでのビルド後に、ちょっとバイナリをZIPで固めたいと思っても簡単にはできません。Visual Studioでのビルドに限らず、Windowsで作業を自動化しようとすると、Linuxならzipコマンド一発でできることが、簡単にできなくて困ることがよくあります。

ZIP.VBSのように頑張ればできないこともないのですが、自分で書く気にはなりません。ZIP.VBSはライセンスが不明瞭なので使いにくいですし、内部でサポート対象外のCopyHereメソッド*1を使っているので将来性が不安です。

そこに現れた救世主が.NET Framework 4.5です。.NET Framework 4.5からZIPファイルを簡単に扱えるようになりました*2。.NETでできることはPowerShellでもできるはずなので、試してみました。

この記事では、以下のサイトを参考にさせていただきました。感謝です。
viziblr - News - Zip up a Folder with PowerShell 3 the Easy Way  

利用出来る環境

この記事の内容を実現するには、.NET Framework 4.5のランタイムと、PowerShell*3が必要です。

.NET Framework 4.5のランタイムは、Windows Vista / Windows Server 2008以降で利用でき、Windows 8 / Windows Server 2012には標準で付属しています。

PowerShellは、Windows XP SP2 / Windows Server 2003 SP1以降で利用でき、Windows 7 / Windows Server 2008 R2以降には標準で付属しています。

参考:

検証環境

※プロジェクトのディレクトリ構成は、C#コンソールアプリケーションのプロジェクトを前提としています。他のプロジェクトだと異なるかもしれません。

ビルド後のスクリプト

プロジェクトのルートに以下のファイルを作ります。真ん中付近にあるzip関数が.NETのSystem.IO.Compression名前空間にあるZipFile.CreateFromDirectoryメソッドを呼び出しています。

package.ps1
param(
    [string]$destFile,
    [string]$srcDir
)

[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem")

function zip([string]$destFile, [string]$srcDir)
{
    $compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal
    $includeBaseDir = $false
    [System.IO.Compression.ZipFile]::CreateFromDirectory($srcDir, $destFile, $compressionLevel, $includeBaseDir)
}

if (Test-Path $destFile)
{
    rm $destFile
}

zip "$destFile" "$srcDir"
ビルド後に実行するコマンドライン

Visual Studioのメニューのデバッグプロジェクトのプロパティ→ビルドイベントと辿り、ビルド後に実行するコマンドラインに以下の内容を設定します。

set TARGET_DIR_WITH_BACKSLASH=$(TargetDir)
set TARGET_DIR_WITHOUT_BACKSLASH=%TARGET_DIR_WITH_BACKSLASH:~0,-1%
set DEST_PATH=%TARGET_DIR_WITHOUT_BACKSLASH%.zip
set SRC_DIR=%TARGET_DIR_WITHOUT_BACKSLASH%
powershell -ExecutionPolicy RemoteSigned -File "$(ProjectDir)package.ps1" "%DEST_PATH%" "%SRC_DIR%"


これでビルドを行うたびに、Debugビルドであればbin\Debugの中身が圧縮されてbin\Debug.zipが作られます。Releaseビルドであればbin\Release.zipが作られます。bin\Debugやbin\Releaseには不要なものも含まれると思いますが、その辺は適当に改造してみてください。

実際にプロジェクトの中に置くと、こんな感じになります。 orangain/kinect-fhc · GitHub

まとめ

現在のところWindows 8 / Windows Server 2012限定ですが、OS標準の環境で比較的簡単にZIPを作れるのは嬉しいです。今までこの程度のことができなかったのは悲しいという見方もあります。さらに言えば、これでもまだ面倒なのでzip/unzipコマンドをデフォルトで用意して欲しいものです。

ちなみに、Windowsで本格的に自動ビルドをやろうとしたら、MSBuildとExtension Packを使うみたいですね。この辺はあまり知らないので勉強していきたいです。

参考:

*1:[http://support.microsoft.com/kb/2679832/ja:title=CopyHere メソッドから Zip ファイルを処理することはできません]

*2:[http://blogs.msdn.com/b/japan_platform_sdkwindows_sdk_support_team_blog/archive/2012/03/27/net-zip.aspx:title]

*3:検証環境に書いてあるように、PowerShell 3.0でしか検証していません。他のバージョンでは動かない可能性もあります。