首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获取或评估MSBuild.exe.config中定义的全局变量的API是什么?

获取或评估MSBuild.exe.config中定义的全局变量的API是什么?
EN

Stack Overflow用户
提问于 2021-07-21 07:15:42
回答 1查看 149关注 0票数 0

我正在编写一个应用程序来评估(但不是构建) *.csproj和其他项目文件。

应用程序模拟MSBuild所做的事情。它使用由Microsoft.Build.dll实例公开的(有文档记录的)公共API,这些API安装在Visual文件夹中,例如:

代码语言:javascript
复制
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\
C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\

在这些目录中,有一个MSBuild.exe.config文件,其中包含一个msbuildToolsets部分,如下所示:

代码语言:javascript
复制
<msbuildToolsets default="Current">
  <toolset toolsVersion="Current">
    <property name="MSBuildToolsPath" value="$([MSBuild]::GetCurrentToolsDirectory())" />
    <property name="MSBuildToolsPath32" value="$([MSBuild]::GetToolsDirectory32())" />
    <property name="MSBuildToolsPath64" value="$([MSBuild]::GetToolsDirectory64())" />
    <property name="MSBuildSDKsPath" value="$([MSBuild]::GetMSBuildSDKsPath())" />
    <property name="FrameworkSDKRoot" value="$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\NETFXSDK\4.8@InstallationFolder)" />
    <property name="MSBuildRuntimeVersion" value="4.0.30319" />
    <property name="MSBuildFrameworkToolsPath" value="$(SystemRoot)\Microsoft.NET\Framework\v$(MSBuildRuntimeVersion)\" />
    ... etc ...

这些条目定义了在计算*.csproj时设置的全局变量的值。

dotnet/msbuild源代码中,我看到:

  • GetMSBuildSDKsPath()这样的函数是在IntrinsicFunctions类(在Microsoft.Build.Evaluation命名空间中)中定义的,它是一个internal static类。
  • 此函数的实现委托给BuildEnvironmentHelper (在Microsoft.Build.Shared命名空间中),这也是一个internal类。

在调用MSBuild时正确设置这些全局变量至关重要,例如,当调用ProjectCollection.LoadProject方法返回Project实例时(否则项目不会加载)。

设置这些变量的API是将它们通过globalProperties参数传递给ProjectCollection --但我不知道如何获取或计算这些属性的值,我应该设置这些属性。

我的问题是-- 如何读取这些变量(考虑到上面列出的类是内部的)?是否有一个公共API可以做到这一点?

如果有必要,我可以在MSBuild bin文件夹中运行我的应用程序,并/或复制MSBuild.exe.config文件。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-14 11:05:40

使用的方法:

  • 设置MSBUILD_EXE_PATH环境变量
  • 实例化BuildParameters
  • 调用其GetToolset方法
  • 参数在工具集的Properties中。

目录路径(例如,Enterprise)可能因机器而异。为了更加健壮,您可以实现一个运行时探测来发现它,而不是硬编码它。

代码语言:javascript
复制
        private readonly string _toolsPath;
        private readonly string _toolsVersion;

        public EvaluateCondition(string solutionPath)
        {
            var toolsets = new Dictionary<string, string>
            {
                {"2.0", @"C:\WINDOWS\Microsoft.Net\Framework\v2.0.50727"},
                {"3.5", @"C:\WINDOWS\Microsoft.Net\Framework\v3.5"},
                {"4.0", @"C:\WINDOWS\Microsoft.Net\Framework\v4.0.30319"},
                {"15.0", @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin"},
                {"Current" /*"16.0"*/, @"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin"}
            };

            // specify which version of the toolset we want to use
            // this is a compile-time definition but could have been a function parameter
#if X2017
            _toolsVersion = "15.0";
#endif
#if X2019
            _toolsVersion = "Current";
#endif

            var toolsPath = toolsets[_toolsVersion];
            _toolsPath = toolsPath; 
            
            // Use BuildParameters to load the settings which are defined in the MSBuild.exe.config and which would be loaded
            // if we specified ToolsetDefinitionLocations.ConfigurationFile as a ProjectCollection constructor parameter.
            Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", CombineFullPath(toolsPath, "MSBuild.exe"));
            var buildParameters = new BuildParameters();
            var toolset = buildParameters.GetToolset(_toolsVersion);
            var toolsetProperties = toolset.Properties;

            GlobalProperties = new Dictionary<string, string>();
            foreach (var kvp in toolsetProperties)
            {
                if (kvp.Key != kvp.Value.Name)
                {
                    throw new ArgumentException();
                }

                GlobalProperties.Add(kvp.Key, kvp.Value.EvaluatedValue);
            }

            Environment.SetEnvironmentVariable("MSBuildExtensionsPath", GlobalProperties["MSBuildExtensionsPath"]);
            Environment.SetEnvironmentVariable("MSBuildSDKsPath", GlobalProperties["MSBuildSDKsPath"]);

            // QED: pass the global variables to the ProjectCollection
            ProjectCollection = new ProjectCollection(GlobalProperties);

            foreach (var kvp in toolsets)
            {
                // this sets $(MSBuildToolsPath)
                ProjectCollection.AddToolset(new Toolset(kvp.Key, kvp.Value, ProjectCollection, string.Empty));
            }
        }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68465375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档