这与TFS 2010 Build System有关。在我们的构建工作流程中,我们使用System.Environment类的SetEnvironmentVariable方法设置了几个环境变量。我已经确认在构建服务器上正确设置了此环境变量,并将其设置为系统范围的环境变量。
问题是,当在这个WF中调用MSBuild并编译解决方案时,我们尝试读取此环境变量的post构建事件失败,因为它们无法看到此环境变量。
有没有办法强制MSBuild重新加载环境变量或强制正在运行的WF重新加载环境变量?我怀疑是即使WF创建了这个变量,它也不会刷新它的Environment状态,因此无法看到变量。此外,由于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");
}
}
}
答案 0 :(得分:2)
不幸的是,因为MSBuild
进程在启动时传递了环境变量的缓存版本,所以该进程的命令行功能将无法查看更新的值。在我看来,你得到的最好的选择是在后期构建事件中更改该变量,或者将值存储在可以从构建后事件中读取的介质中。
好的,所以下面的陈述(可以找到here)我认为解释哪里来自环境变量为什么你不是在MSBuild
中获取更新版本。
默认情况下,子进程继承其父进程的环境变量。
所以,两个人可以在那个游戏中玩,让我们只是广播说发生了变化,看看是否会为我们照顾它。以下是应该为您执行此操作的代码。
[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;
int result;
SendMessageTimeout(
(System.IntPtr)HWND_BROADCAST,
WM_SETTINGCHANGE,
0,
"Environment",
SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG,
SomeTimeoutValue,
out result);