3

microsoft.build.utilities.task を実装するときに、ビルドのさまざまな環境変数にアクセスするにはどうすればよいですか?

たとえば、「TargetPath」

タスク XML の一部として渡すことができることはわかっています。

<MyTask TargetPath="$(TargetPath)" />

しかし、コードで変数にアクセスできる場合、タスクの消費者にそれを強制する必要はありません。

http://msdn.microsoft.com/en-us/library/microsoft.build.utilities.task.aspx

4

2 に答える 2

5

私はこれを行う方法を考え出しました

public static class BuildEngineExtensions
{
    const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public;

    public static IEnumerable GetEnvironmentVariable(this IBuildEngine buildEngine, string key,bool throwIfNotFound)
    {
        var projectInstance = GetProjectInstance(buildEngine);

        var items = projectInstance.Items
            .Where(x => string.Equals(x.ItemType, key, StringComparison.InvariantCultureIgnoreCase)).ToList();
        if (items.Count > 0)
        {
            return items.Select(x => x.EvaluatedInclude);
        }


        var properties = projectInstance.Properties
            .Where(x => string.Equals(x.Name, key, StringComparison.InvariantCultureIgnoreCase)).ToList();
        if (properties.Count > 0)
        {
            return properties.Select(x => x.EvaluatedValue);
        }

        if (throwIfNotFound)
        {
            throw new Exception(string.Format("Could not extract from '{0}' environmental variables.", key));
        }

        return Enumerable.Empty();
    }

    static ProjectInstance GetProjectInstance(IBuildEngine buildEngine)
    {
        var buildEngineType = buildEngine.GetType();
        var targetBuilderCallbackField = buildEngineType.GetField("targetBuilderCallback", bindingFlags);
        if (targetBuilderCallbackField == null)
        {
            throw new Exception("Could not extract targetBuilderCallback from " + buildEngineType.FullName);
        }
        var targetBuilderCallback = targetBuilderCallbackField.GetValue(buildEngine);
        var targetCallbackType = targetBuilderCallback.GetType();
        var projectInstanceField = targetCallbackType.GetField("projectInstance", bindingFlags);
        if (projectInstanceField == null)
        {
            throw new Exception("Could not extract projectInstance from " + targetCallbackType.FullName);
        }
        return (ProjectInstance)projectInstanceField.GetValue(targetBuilderCallback);
    }
}

そしてこんな風に使えます

string targetPath = buildEngine.GetEnvironmentVariable("TargetPath", true).First();
string intermediateAssembly = buildEngine.GetEnvironmentVariable("IntermediateAssembly", true).First();
IEnumerable<string> referencePaths = buildEngine.GetEnvironmentVariable("ReferencePath", true);

はい、それは醜い黒魔術ですが、機能します。

于 2011-05-22T04:56:18.077 に答える
2

これを簡単に行うことはできませんし、行うべきではありません。タスクは、実行のコンテキストを認識してはならず、入力パラメーターで動作する必要があります。

免責事項:やらないでください!

本当にやりたい場合は、プロジェクトファイルをそのようなもので再解析する必要があります。

public override bool Execute()
{
  string projectFile = BuildEngine.ProjectFileOfTaskNode;

  Engine buildEngine = new Engine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory());

  Project project = new Project(buildEngine);
  project.Load(projectFile);
  foreach(var o in project.EvaluatedProperties)
  {
    // Use properties
  }

  // Do what you want

  return true;
}
于 2010-06-15T08:39:37.320 に答える