3

これは、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");
        }
    }
}
4

1 に答える 1

2

残念ながら、MSBuildプロセスは起動時にキャッシュされたバージョンの環境変数が渡されるため、そのプロセスのコマンドライン機能は更新された値を表示できません。私の意見では、ビルド後のイベントでその変数を変更するか、ビルド後のイベントから読み取ることができるメディアに値を格納するのが最善の策です。

アップデート

さて、以下のステートメント(ここにあります)は、環境変数がどこから来ているのか、そしてなぜで更新されたバージョンを取得していないのかを説明していると思いますMSBuild

デフォルトでは、子プロセスはその親プロセスの環境変数を継承します。

したがって、2人でそのゲームをプレイできます。変更が発生したことをブロードキャストして、それで問題が解決するかどうかを確認しましょう。以下はあなたのためにそれをするべきコードです。

[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);
于 2012-09-11T17:07:25.307 に答える