たんたかさんが PHPでRoleEnvironmentを使う というへんたい素晴らしいPostをしてたのでもっと手軽にできないかなーと。
もともとWindows Azure SDK 1.5以上でサービス定義ファイルにxPathを使用してRoleEnvironmentの値を環境変数にセットできるのですが、これがちょっと曲者。
というのもサービス定義ファイルのEnvironment要素に指定した環境変数はプロセス環境変数で、つまりRoleEntryPointがあるプロセスでしか見れません。
これはどういうことかというと、別プロセスとして動作するFull IISや、たとえばPHPなどからはせっかくの値が見れないってことですね。
これは不便極まりない!ということで冒頭のたんたかさんのBlogにあるようなHackが必要なわけですが、もっとお手軽にできるんじゃない?ということで試してみました。
まずサンプルということで、ASP.NET MVCで環境変数を出力するようなアプリを作っておきます。
<h1>Machine</h1>
<table>
@foreach (System.Collections.DictionaryEntry env in Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine)) {
<tr>
<td>@env.Key</td>
<td>@env.Value.ToString()</td>
</tr>
}
</table>
</p>
<p>
<h1>Process</h1>
<table>
@foreach (System.Collections.DictionaryEntry env in Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process)) {
<tr>
<td>@env.Key</td>
<td>@env.Value.ToString()</td>
</tr>
}
</table>
</p>
<p>
<h1>User</h1>
<table>
@foreach (System.Collections.DictionaryEntry env in Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User)) {
<tr>
<td>@env.Key</td>
<td>@env.Value.ToString()</td>
</tr>
}
</table>
</p>
適当にViewにはっておきましょう。
さてやること1つ目。サービス定義ファイルに環境変数を追加します。
<ServiceDefinition name="WindowsAzureProject3" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="MvcWebRole1" vmsize="ExtraSmall">
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
</Endpoints>
<Runtime>
<Environment>
<Variable name="EnvironmentTest1">
<RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/Endpoints/Endpoint[@name='Endpoint1']/@address" />
</Variable>
<Variable name="EnvironmentTest2" value="EnvironmentTest2Value" />
</Environment>
</Runtime>
<Startup>
<Task commandLine="env.bat" executionContext="elevated" taskType="simple">
<Environment>
<Variable name="ENVIRONMENT3">
<RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/Endpoints/Endpoint[@name='Endpoint1']/@address" />
</Variable>
</Environment>
</Task>
</Startup>
</WebRole>
</ServiceDefinition>
上記のEnvrionmentTest1、EnvrionmentTest2、Envrionment3はそれぞれテスト用です。後で見たらわかりますが、これらの値はASP.NETなアプリ(別プロセス)からは参照できません。
で、ここでのポイントはStartup要素以下のEnvrionmentですね。ここでスタートアップタスクに環境変数を渡してるのですがこのままだとStartupTaskのプロセスが終わったら消えてしまいます。
ということで、StartupTask内でプロセス環境変数をシステム環境変数につけかえましょう。
@echo off setx ENVIRONMENT4 %ENVIRONMENT3% /M
Setxコマンドに/M引数つけてシステム環境変数に設定してるだけです。簡単!
注意点はシステム環境変数に設定するのでStartupTaskを管理者権限(Elevated)で動作させてるのと、システム環境変数を参照するには設定終わった後にプロセスが起動しないといけないのでtaskTypeをsimpleにして他のプロセスより先に実行されるようにしてるところでしょうか。
もし他にもStartupTaskがあるのであれば、優先順位を付けたりするといいかもです。
さて実際にデプロイして確かめてみましょう。
他の環境変数は取れてませんが、StartupTaskで付け替えたシステム環境変数はバッチリ取れてますね。
これで非.NETアプリ等でもシステム環境変数さえ触れればRoleEnvrionmentの値を触ることができますね!