MSBuild属性范围

MSBuild属性范围,msbuild,msbuild-propertygroup,Msbuild,Msbuild Propertygroup,我再一次和MSBuild战斗。我想用根路径定义一个属性值。作为构建的一部分,将使用版本信息更新路径。然而,MSBuild似乎有自己的作用域规则,这些规则似乎完全是反向的。以第一个例子为例: <?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> <Property

我再一次和MSBuild战斗。我想用根路径定义一个属性值。作为构建的一部分,将使用版本信息更新路径。然而,MSBuild似乎有自己的作用域规则,这些规则似乎完全是反向的。以第一个例子为例:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">

  <PropertyGroup>
    <MyPath>\\server\folder</MyPath>
  </PropertyGroup>

  <Target Name="Main">
    <Message Text="In Main Before - MyPath = $(MyPath)"/>
    <CallTarget Targets="Task1" />
    <CallTarget Targets="Task2" />
    <CallTarget Targets="Task3" />
    <Message Text="In Main After - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task1">
    <PropertyGroup>
        <MyPath>$(MyPath)\version5</MyPath>
    </PropertyGroup>
    <Message Text="In Task1 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task2">
    <Message Text="In Task2 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task3">
    <Message Text="In Task3 - MyPath = $(MyPath)"/>
  </Target>

</Project>
现在,在主目标中设置MyPath变量的版本略有不同:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">

  <PropertyGroup>
    <MyPath>\\server\path</MyPath>
  </PropertyGroup>

  <Target Name="Main">
    <Message Text="In Main Before - MyPath = $(MyPath)"/>
    <PropertyGroup>
        <MyPath>$(MyPath)\version5</MyPath>
    </PropertyGroup>
    <Message Text="In Main After PropertyGroup - MyPath = $(MyPath)"/>
    <CallTarget Targets="Task1" />
    <CallTarget Targets="Task2" />
    <CallTarget Targets="Task3" />
    <Message Text="In Main After - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task1">
    <Message Text="In Task1 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task2">
    <Message Text="In Task2 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task3">
    <Message Text="In Task3 - MyPath = $(MyPath)"/>
  </Target>

</Project>

我已经查看了该站点上类似的其他链接,但它们似乎都是从MSBuild项目文件中调用MSBuild任务。我只想更新路径,让它在项目中的任何地方都可用。有什么想法吗?

这是一个非常有趣的问题,在下面的文章中,我们将通过示例对其进行深入研究:

基本上,在目标执行过程中使用本地和全局上下文切换有一些技巧:

  • 为脚本创建一个项目类实例,并 包含全局视图中属性和项的所有值 上下文
  • 执行目标时,全局上下文将复制到本地上下文中 目标将使用的上下文
  • A在目标执行结束时,将合并本地上下文更新 回到全球环境
  • 在目标执行完成之前,不会进行本地更新 可由使用CallTarget或MSBuild任务调用的目标访问

基于sll的答案,将设置新路径的目标设置为依赖项,而不是使用
CallTarget
将产生预期的行为:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">

  <PropertyGroup>
    <MyPath>\\server\folder</MyPath>
  </PropertyGroup>

  <Target Name="Main" DependsOnTargets="SetMyPathProperty">
    <Message Text="In Main Before - MyPath = $(MyPath)"/>
    <CallTarget Targets="Task1" />
    <Message Text="In Main After - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="SetMyPathProperty">
    <PropertyGroup>
      <MyPath>$(MyPath)\version5</MyPath>
    </PropertyGroup>
  </Target>

  <Target Name="Task1">
    <Message Text="In Task1 - MyPath = $(MyPath)"/>
  </Target>

</Project>

将SetMyPathProperty设置为Task1的依赖项而不是Main将导致与PropertyScopeTest1.proj相同的行为。

此解决方案对我来说更有意义。我计划明天试试这个,看看它是否适用于我的用例。刚刚尝试了这个解决方案,它正是我想要的。非常感谢!
Project "C:\Temp\PropertyScopeTest2.proj" on node 1 (Main target(s)).
Main:
  In Main Before - MyPath = \\server\path
  In Main After PropertyGroup - MyPath = \\server\path\version5
Task1:
  In Task1 - MyPath = \\server\path
Task2:
  In Task2 - MyPath = \\server\path
Task3:
  In Task3 - MyPath = \\server\path
Main:
  In Main After - MyPath = \\server\path\version5
Done Building Project "C:\Temp\PropertyScopeTest2.proj" (Main target(s)).
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">

  <PropertyGroup>
    <MyPath>\\server\folder</MyPath>
  </PropertyGroup>

  <Target Name="Main" DependsOnTargets="SetMyPathProperty">
    <Message Text="In Main Before - MyPath = $(MyPath)"/>
    <CallTarget Targets="Task1" />
    <Message Text="In Main After - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="SetMyPathProperty">
    <PropertyGroup>
      <MyPath>$(MyPath)\version5</MyPath>
    </PropertyGroup>
  </Target>

  <Target Name="Task1">
    <Message Text="In Task1 - MyPath = $(MyPath)"/>
  </Target>

</Project>
Main:
  In Main Before - MyPath = \\server\folder\version5
Task1:
  In Task1 - MyPath = \\server\folder\version5
Main:
  In Main After - MyPath = \\server\folder\version5