Windows Azure におけるシンボリックリンク作成について
前回のエントリでは、Windows Azureのローカルリソースを使った場合にパスの長さが問題になるかも知れませんと記述しました。何故かという理由を以下に示します。
- Windows Azure上のローカルリソースは、リソースドライブに中で「guid.リソース名」という名前が付与されます。このために、指定したリソース名の正式なフォルダー名はかなり長くなります。
- Development Fabricでは、「%UserProfile%\AppData\Local\dftmp\s0\deployment id\res\instance id\diirectory\リソース名」になります。
Development Fabricを使ったテストでは、長いパスの問題が顕著に発生する傾向にあります。これを回避するには、コマンドプロンプト(cmd.exe)が用意しているコマンドである「mklink」を活用する必要があります。mklinkの良く使うオプションを以下に示します。
- mklink シンボリックリンク名 リンク元のファイル名
- mklink /d シンボリックリンク名 リンク元のフォルダ名
mklinkコマンドで作成するシンボリックリンクですが、コマンドの入力時に存在しないファイル名かフォルダー名である必要があります。単純に言えば、新しいファイルシステムのアイテムを作成するので、同名のアイテムがあるとエラーになるということです。無事に作成できると、dirコマンドでは「2011/08/19 16:49 <SYMLINKD> リンク先名 [リンク元名]」と表示されます。シンボリックリンクを削除するには、rmコマンドやdelコマンドやWindows エクスプローラーを使う必要があります。特にシンボリックリンクのフォルダーを削除するのに、.NET FrameworkのDirectoryクラスやDirectoryInfoクラスを使用してはいけません。その理由は、リンク元のフォルダーが削除されてしまうからです。この理由から、C#などではProcessクラスを使用する必要があります。以下にサンプルコードを示します。
static bool CreateSymbolicLink(string linkDestination, string linkSource)
{
var cmdexe = new ProcessStartInfo("cmd.exe");
cmdexe.WorkingDirectory = System.Environment.CurrentDirectory;
cmdexe.UseShellExecute = false;
var proc = new Process();
cmdexe.Arguments = "/c mklink /d " +
linkDestination + " " +
linkSource;
proc.StartInfo = cmdexe;
proc.Start();
proc.WaitForExit();
}
このサンプルでは、ProcessStartInfo.UseShellExecuteプロパティをfalseにしているために、cmd.exeに対して「/c」オプション付きでmklinkコマンドを設定しています。これをDevelopment Fabricなどで利用する場合は、シンボリックリンクが存在している場合に削除するコードも用意した方が良いでしょう。
var cmdexe = new ProcessStartInfo("cmd.exe");
cmdexe.WorkingDirectory = System.Environment.CurrentDirectory;
cmdexe.UseShellExecute = false;
var proc = new Process();
// シンボリックリンクが存在すれば削除する
if (Directory.Exists(linkDestination))
{
cmdexe.Arguments = "/c rd " + linkDestination;
proc.StartInfo = cmdexe;
proc.Start();
proc.WaitForExit();
}
この理由は、デバッグ実行する毎にDevelopment Fabricに対するDeployment Idが変化するために、デバッグを終了するとDevelopment Fabricが使用した一時ファイルを削除しだし、リンク元が存在しないシンボリックリンクになってしまうからです。ここまでの例では、UseShellExecuteプロパティをfalseで使用していますが、trueにして使用することもできます。この場合は、コマンドとしてmklinkだけを設定することができます。UseShellExecuteプロパティをfalseにしたサンプルを提示した理由は、エラー処理にあります。サンプルにエラー処理は含めていませんが、Windows Azureのロールインスタンスなどで呼び出す場合にUIが無い前提でエラー処理を厳密に記述する必要があるからです。従って、RedirectStandardErrorプロパティをtrueに設定して、標準エラー出力を処理することでエラー処理を記述する必要があるわけです。