これは、TFS2010ビルドシステムに関連しています。ビルドワークフロー内で、System.EnvironmentクラスのSetEnvironmentVariableメソッドを使用していくつかの環境変数を設定します。この環境変数がビルドサーバーで正しく設定され、システム全体の環境変数として設定されることを確認しました。
問題は、MSBuildがこのWF内で呼び出され、ソリューションをコンパイルすると、この環境変数を読み取ろうとするビルド後のイベントが、この環境変数を認識できないために失敗することです。
MSBuildに環境変数の再読み込みを強制したり、実行中のWFに環境変数の再読み込みを強制したりする方法はありますか?私の疑惑は、WFがこの変数を作成しても、環境状態を更新しないため、変数を表示できないということです。さらに、WFはMSBuildを呼び出すため、この変数を含まないMSBuildに同じ環境状態を渡します。
アップデート
次のコードをVisualStudioに貼り付けて、実行します。SendMessageTimeOutまでの遅延は10秒なので、しばらくお待ちください。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace EnvironmentVarTest
{
class Program
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool
SendMessageTimeout(
IntPtr hWnd,
int Msg,
int wParam,
string lParam,
int fuFlags,
int uTimeout,
out int lpdwResult
);
public const int HWND_BROADCAST = 0xffff;
public const int WM_SETTINGCHANGE = 0x001A;
public const int SMTO_NORMAL = 0x0000;
public const int SMTO_BLOCK = 0x0001;
public const int SMTO_ABORTIFHUNG = 0x0002;
public const int SMTO_NOTIMEOUTIFNOTHUNG = 0x0008;
static void Main(string[] args)
{
Program p = new Program();
string environmentVariableValue = DateTime.Now.ToLongTimeString().Replace(":", String.Empty);
Console.WriteLine("On the CMD window that opens up after about 10 seconds, if you type %samplevar% and hit Enter, you should see: " + environmentVariableValue);
p.SetEnvironmentVariable(environmentVariableValue);
RefreshProcessVars();
p.ReadEnvironmentVariable();
p.StartCMD();
Console.ReadLine();
}
void SetEnvironmentVariable(string value)
{
System.Environment.SetEnvironmentVariable("samplevar", value, EnvironmentVariableTarget.Machine);
}
static void RefreshProcessVars()
{
int result;
bool callresult = SendMessageTimeout(
(System.IntPtr)HWND_BROADCAST,
WM_SETTINGCHANGE,
0,
"Environment",
SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG,
10000,
out result);
if (!callresult || result == 0)
{
int lasterror = Marshal.GetLastWin32Error();
Win32Exception winex = new Win32Exception(lasterror);
Console.WriteLine("Exception happened while calling SendMessageTimeOut. The exception message is " + winex.Message);
}
}
void ReadEnvironmentVariable()
{
var x = System.Environment.GetEnvironmentVariable("smaplevar", EnvironmentVariableTarget.Machine);
}
void StartCMD()
{
Process.Start("cmd.exe");
}
}
}