【问题标题】:Find a file in the parent folders with msbuild使用 msbuild 在父文件夹中查找文件
【发布时间】:2011-11-23 11:31:48
【问题描述】:

在 MsBuild 中,可以创建一个 build.proj.user 文件,该文件由 Microsoft.Common.Targets 构建文件解析。

我希望有一个类似的系统,可以在文件夹的根目录中放置一个 .user 文件,并让 msbuild 从该文件中获取配置设置。

以这些路径为例:

c:\working\build.proj.user
c:\working\solution1\build.proj.user
c:\working\solution1\project1\
c:\working\solution1\project2\
c:\working\solution1\project3\build.proj.user

c:\working\solution2\
c:\working\solution2\project1\
c:\working\solution2\project2\

我想为解决方案1/项目1读取文件c:\working\solution1\build.proj.user,为解决方案2/项目1读取文件c:\working\build.proj.user

目的是允许为每个解决方案和/或项目定制集成测试连接字符串属性。

目前我看到的解决方案是:

  • 创建一个自定义 msbuild 任务,该任务将查找此文件
  • 构造一个 shell 命令来查找文件。
  • 在父路径的父路径和父路径中硬编码查看

我不喜欢这两种解决方案,我想知道是否没有更优雅的方式来实现我的目标(使用 msbuild)。

【问题讨论】:

    标签: .net-3.5 msbuild


    【解决方案1】:

    此功能存在于 MSBuild 4.0 中:$([MSBuild]::GetDirectoryNameOfFileAbove(directory, filename)

    示例:在祖先目录中包含一个名为“Common.targets”的文件

    <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Common.targets))\Common.targets" 
        Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Common.targets))' != '' " />
    

    查看这篇博文了解更多详情:MSBuild Property Functions

    【讨论】:

      【解决方案2】:

      将此添加到您的项目文件中:

      <Import Project="build.proj.user" Condition="Exists('build.proj.user')"/>
      <Import Project="..\build.proj.user" Condition="!Exists('build.proj.user') and Exists('..\build.proj.user')"/>
      <Import Project="..\..\build.proj.user" Condition="!Exists('build.proj.user') and !Exists('..\build.proj.user') and Exists('..\..\build.proj.user')"/>
      

      编辑: 您也可以使用MsBuild inline task 进行操作。它有点慢,但更通用:) MsBuild 4.0 支持内联任务

      <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="4.0">
        <UsingTask TaskName="FindUserFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
          <ParameterGroup>
            <CurrentDirName ParameterType="System.String" Required="true" />
            <FileToFind ParameterType="System.String" Required="true" />
            <UserFileName ParameterType="System.String" Output="true" />
          </ParameterGroup>
          <Task>
            <Using Namespace="System"/>
            <Using Namespace="System.IO"/>
            <Code Type="Fragment" Language="cs">
              <![CDATA[
                Log.LogMessage("FindUserFile parameters:");
                Log.LogMessage("CurrentDirName = " + CurrentDirName);
                Log.LogMessage("FileToFind = " + FileToFind);
      
                while(CurrentDirName != Directory.GetDirectoryRoot(CurrentDirName) && !File.Exists(CurrentDirName + Path.DirectorySeparatorChar + FileToFind))
                   CurrentDirName = Directory.GetParent(CurrentDirName).FullName;
                if(File.Exists(CurrentDirName + Path.DirectorySeparatorChar + FileToFind)) 
                   UserFileName = CurrentDirName + Path.DirectorySeparatorChar + FileToFind;
      
                Log.LogMessage("FindUserFile output properties:");
                Log.LogMessage("UserFileName = " + UserFileName);
              ]]>
            </Code>
          </Task>
        </UsingTask>
      
        <Target Name="FindUserFileTest" >
          <FindUserFile CurrentDirName="$(MSBuildThisFileDirectory)" FileToFind="build.proj.user">
           <Output PropertyName="UserFileName" TaskParameter="UserFileName" />
          </FindUserFile>
      
          <Message Text="UserFileName = $(UserFileName)"/>
          <Error Condition="!Exists('$(UserFileName)')" Text="File not found!"/>
      
        </Target>
      </Project>
      

      它是如何工作的: FindUserFile 是用 C# 语言编写的内联任务。它尝试查找 FileToFind 参数中指定的文件。然后遍历所有父文件夹,并在 UserFileName 输出属性中返回 FileToFind 文件的第一次出现。如果未找到文件,则 UserFileName 输出属性为空字符串。

      【讨论】:

      • 这是解决问题的方法,但我一直在寻找更通用的解决方案,让 msbuild 一直向上查找,直到驱动器的根目录。
      • 只需再往下添加几个级别。除非您习惯为您的项目创建 50 级深度目录,否则应该可以解决您的问题。我同意,这不是最优雅的方式,但在这种情况下,自定义任务将无济于事。在解析所有 文件后执行任务。
      • 感谢您的建议,我会使用第一个,直到我们可以使用 MsBuild 4.0
      猜你喜欢
      • 1970-01-01
      • 2011-03-03
      • 2011-06-18
      • 2015-10-03
      • 1970-01-01
      • 2019-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多