Это связано с системой сборки TFS 2010. В нашем рабочем процессе сборки мы устанавливаем пару переменных среды, используя метод SetEnvironmentVariable класса System.Environment. Я подтвердил, что эта переменная среды правильно устанавливается на сервере сборки и устанавливается как общесистемная переменная среды.
Проблема в том, что когда MSBuild вызывается в этом WF и компилирует решения, наши события пост-сборки, которые пытаются прочитать эту переменную среды, терпят неудачу, поскольку они не могут видеть эту переменную среды.
Есть ли способ заставить MSBuild перезагрузить переменные среды или заставить работающий WF перезагрузить переменные среды? Я подозреваю, что даже несмотря на то, что WF создает эту переменную, он не обновляет свое состояние среды и, следовательно, не может видеть переменную. Кроме того, поскольку WF вызывает MSBuild, он передает то же состояние среды в MSBuild, которое не содержит эту переменную.
Обновить
Вставьте следующий код в Visual Studio и запустите его. Задержка 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");
}
}
}