13

I have a shared properties file shared.properties.proj

<Project  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <SharedAssemblySearch>$(MSBuildProjectDirectory)\..\Shared Assemblies</SharedAssemblySearch>
    <ParentDir>..</ParentDir>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblyPath Condition="Exists('$(SharedAssemblySearch)')">$(SharedAssemblySearch)</SharedAssemblyPath>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">..\SharedAssemblies</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblyPath Condition="Exists('$(SharedAssemblySearch)')">$(SharedAssemblySearch)</SharedAssemblyPath>
 </PropertyGroup>
</project>

I am searching for whatever level parent directory contains the directory named Shared Assemblies. or alternatively SharedAssemblies

I'd like to put this code in a central location for the sln, so that all the projects can just import it. projects in the sln are not all at the same hierarchy level.

Sample .csproj

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Shared.Properties.proj))\Shared.Properties.proj"
   Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Shared.Properties.proj))' != '' "/>
    <ItemGroup>
    <Reference Include="EntityFramework">
      <HintPath>$(SharedAssemblyPath)\NuGet\EntityFramework.4.3.0\lib\net40\EntityFramework.dll</HintPath>
     </Reference>
    </ItemGroup>
  <Target Name="CheckReferencePaths" BeforeTargets="ResolveAssemblyReferences">
    <Message Importance="high" Text="Doing CheckReferencePaths" />
    <ItemGroup>
     <SharedAssemblyPathItem Include="$(SharedAssemblyPath)" />
    </ItemGroup>
    <Warning Condition="!Exists('@(SharedAssemblyPathItem)')" Text="SharedAssemblyPath not found at '@(SharedAssemblyPathItem)'" />
    <Warning Condition="!Exists('@(SharedAssemblyPathItem)')" Text="SharedAssemblyPath not found at '@(SharedAssemblyPathItem->'%(FullPath)')'" />
    <Message Condition="!Exists('%(Reference.HintPath)')" Text="FullPath=%(Reference.HintPath)" Importance="high" />

I have this working in the main project without pushing the property group out to a satellite file that I import, but now want to make it reusable between other projects that could have shared references.

The BeforeTargets target shows this on the new attempt that is not working:

CheckReferencePaths: Doing CheckReferencePaths D:\projects\Team\Project\Adapters\DbAdapter\dbadapter.csproj(103,5): warning : SharedAssemblyPath not found at '' D:\projects\Team\Project\Adapters\DbAdapter\dbadapter.csproj(104,5): warning : SharedAssemblyPath not found at ''
FullPath=\NuGet\EntityFramework.4.3.0\lib\net40\EntityFramework.dll
FullPath=

How can I get the project file that imports the shared to evaluate the imported project's properties before it evaluates the item groups' hintpaths. Or is the evaluation order proper, but something else in my construction is incorrect?

4

2 回答 2

19

您的问题使我在MSDN上找到了这些有价值的信息。我在这里发布它是为了保持答案自包含


评估顺序

当 MSBuild 到达Import元素时,导入的项目将有效地插入到Import元素所在位置的导入项目中。因此,Import元素的位置会影响属性和项的值。了解导入项目设置的属性和项目以及导入项目使用的属性和项目非常重要。

项目构建时,首先评估所有属性,然后是项目。例如,以下 XML 定义了导入的项目文件 MyCommon.targets:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Name>MyCommon</Name>
    </PropertyGroup>

    <Target Name="Go">
        <Message Text="Name='$(Name)'"/>
    </Target>
</Project>

以下 XML 定义了导入 MyCommon.targets 的 MyApp.proj:

<Project
    DefaultTargets="Go"
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Name>MyApp</Name>
    </PropertyGroup>
    <Import Project="MyCommon.targets"/>
</Project>

项目构建时,将显示以下消息:

名称="MyCommon"

因为项目是在 MyApp.proj 中定义 Name 属性之后导入的,所以 MyCommon.targets 中 Name 的定义会覆盖 MyApp.proj 中的定义。如果在定义属性名称之前导入项目,则构建将显示以下消息:

名称="我的应用程序"

导入项目时使用以下方法

  1. 在项目文件中定义用作导入项目中的属性和项的参数的所有属性和项。

  2. 导入项目。

  3. 在项目文件中定义必须覆盖导入项目中属性和项的默认定义的所有属性和项。

例子

下面的代码示例显示了第二个代码示例导入的 MyCommon.targets 文件。.targets 文件评估来自导入项目的属性以配置构建。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Flavor Condition="'$(Flavor)'==''">DEBUG</Flavor>
        <Optimize Condition="'$(Flavor)'=='RETAIL'">yes</Optimize>
        <appname>$(MSBuildProjectName)</appname>
    <PropertyGroup>
    <Target Name="Build">
        <Csc Sources="hello.cs"
            Optimize="$(Optimize)"
            OutputAssembly="$(appname).exe"/>
    </Target>
</Project>

下面的代码示例导入 MyCommon.targets 文件。

<Project DefaultTargets="Build"
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Flavor>RETAIL</Flavor>
    </PropertyGroup>
    <Import Project="MyCommon.targets"/>
</Project>
于 2012-03-28T14:43:14.643 回答
-1

尝试使用内联任务而不是 shared.properties.proj 文件。检查我对这个问题的回答。

这是关于搜索一些文件是父目录。您可以调整它以搜索父目录。

于 2012-03-02T21:42:11.757 回答