environment-variables - MSBuild 无法查看从生成工作流设置的环境变量

标签 environment-variables workflow-foundation-4 tfsbuild msbuild-4.0

这与 TFS 2010 构建系统有关。在我们的构建工作流程中,我们使用 System.Environment 类的 SetEnvironmentVariable 方法设置了几个环境变量。我已确认此环境变量已在构建服务器上正确设置,并且已设置为系统范围的环境变量。

问题是,当在此 WF 中调用 MSBuild 并编译解决方案时,我们尝试读取此环境变量的构建后事件失败,因为它们无法看到此环境变量。

有没有办法强制 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("samplevar", EnvironmentVariableTarget.Machine);

        }

        void StartCMD()
        {
            Process.Start("cmd.exe");
        }
    }
}

最佳答案

不幸的是,因为 MSBuild 进程在启动时传递了环境变量的缓存版本,所以该进程的命令行功能将无法看到更新后的值。在我看来,最好的办法是在构建后事件中更改该变量,或者将值存储在可以从构建后事件中读取的介质中。

更新

好的,下面的语句(可以在 here 中找到)我认为解释了环境变量的位置以及为什么你没有得到MSBuild 中的更新版本。

By default, a child process inherits the environment variables of its parent process.

所以,两个人可以玩那个游戏,让我们广播已经发生的变化,看看它是否会为我们解决。下面是应该为您执行此操作的代码。

[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);

关于environment-variables - MSBuild 无法查看从生成工作流设置的环境变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12371630/

相关文章:

c# - Process.Start 无法正确运行批处理文件

workflow-foundation-4 - Windows 工作流基础的基于 Web 的设计器

.net-4.0 - 关于 .NET 4.0 Workflow Foundation 中的 Argument<T> 和 Variable<T> 的混淆

cmd - 使用cmd获取没有系统路径的当前用户路径变量

php - dotenv 在生产环境中需要 .env 文件

c# - TFS 2012 Team Build 获取解决方案配置

c# - TfvcTemplate.12.xaml 构建配置在哪里

tfs - 耻辱警报生成监视器,无法连接到 TFS 2008 或 TFS 2012

python-3.x - Anaconda 新环境在异步函数内给了我 python SyntaxError 'yield'

workflow-foundation - WF 和 nServiceBus 是否重叠?如何?使用哪个?