构建动态引用项目的配置

时间:2016-05-25 22:13:10

标签: c# visual-studio visual-studio-2015 msbuild

我有一个包含在多个解决方案中的ASP.NET项目。在每个解决方案中,我都希望将一个不同的未引用的项目包含在ASP.NET项目的构建输出中。解决方案如下所示:

  • Foo.sln

    • WebApp.csproj
    • Foo.csproj
  • Bar.sln

    • WebApp.csproj
    • Bar.csproj

理想情况下,即使使用F5进行调试,这也可以正常工作。我尝试使用构建配置执行此操作,但在Visual Studio中工作时,偏离典型的“调试”和“发布”似乎很脆弱。有没有一种典型的方法呢?

2 个答案:

答案 0 :(得分:1)

我不知道是否有一种典型的方法可以满足您的要求(来自IDE),但您可以通过编辑*。* proj文件手动完成此操作。

每个项目都会发出输出(* .dll,* .exe,app.config等),它将被复制到 $(OutputPath)属性中指定的文件夹(内部它)将使用OutDir属性)。如果您要构建解决方案,您将拥有 $(SolutionDir)属性,以及 $(SolutionName)。因此,您可以定义新的msbuild项目,该项目将被其他项目引用,您可以设置属性$(OutputPath),以便每个输出都将进入一个文件夹(让我们称之为Common.props):

<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <SolutionDir Condition=" '$(SolutionDir)' == '' ">$(MSBuildThisFileDirectory)<SolutionDir>
    <SolutionName Condition=" '$(SolutionName)' == '' " >DefaultSlnName</SolutionName>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <OutputPath>$(SolutionDir)$(SolutionName)\bin\$(Configuration)</OutputPath>
  </PropertyGroup>
</Project>

之后,您应该通过其他项目导入该项目 - *。* proj(您应该指定项目的正确路径):

<Import Project="..\Common.props"  Condition="Exists('..\Common.props')" />

使用常见的 $(OutputPath)属性会将所有二进制文件放到一个文件夹中 - 这有助于解决您的任务。

答案 1 :(得分:1)

免责声明:我认为这不是一个好主意,但似乎可以做到。

为了测试这个解决方案,我创建了两个项目。 ConsoleApplication1和ClassLibrary1。 ConsoleApplication1没有对ClassLibary1的引用(在Visual Studio中可见),但是当从Visual Studio构建ConsoleApplication1时,它将构建然后将ClassLibary1.dll复制到ConsoleApplication1的bin文件夹。

要导入目标文件,您将继续将此行添加到要构建未引用项目的项目中。此路径将相对于当前项目,因此在我的情况下,目标文件位于我的解决方案的根目录。请务必在<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />行之后添加此内容,因为unreferenced.target依赖于Microsoft.CSharp.targets中设置的目标。

<Import Project="..\unreferenced.target" />

然后你将继续创建一个文件名unreferenced.target并将下面的内容添加到文件中。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <!-- Start another msbuild task to build your unreferenced project -->
 <Target Name="BuildBeforeResolveReferences" BeforeTargets="BeforeResolveReferences">
    <MSBuild
      BuildInParallel="False"
      Projects="$(SolutionDir)ClassLibrary1\ClassLibrary1.csproj"
      RunEachTargetSeparately="True"
      StopOnFirstFailure="False"
      UnloadProjectsOnCompletion="False">
    </MSBuild>
  </Target>

  <Target Name="CopyUnreferencedProjectOutput" AfterTargets="Build">
    <!-- This item group is here because we do not want it evaluated by msbuild until the ClassLibrary1.csproj has been compiled and its output is in its output directory -->
    <ItemGroup>
      <!-- Gets a list of all files at the OutputPath that end in .dll if you need the pdbs remove the .dll -->
      <!-- To maintain folder structure in the bin folder use <SourceFiles Include="..\ClassLibary1\@(OutputPath)**\*.dll" /> the double ** is a recursive wild card and will look through all directorys -->
      <SourceFiles Include="$(MSBuildProjectDirectory)\..\ClassLibrary1\$(OutputPath)*.dll" />
    </ItemGroup>

    <!-- To make sure the copy maintains folder structure switch it to this copy -->
    <!-- <Copy SourceFiles="@(SourceFiles)" DestinationFiles="@(SourceFiles -> '$(MSBuildProjectDirectory)$(OutputPath)%(RecursiveDir)%(Filename)%(Extension)')" /> -->
    <Copy SourceFiles="@(SourceFiles)" DestinationFolder="$(MSBuildProjectDirectory)\$(OutputPath)" />
  </Target>

  <!-- Cleans up all the files when clean is called -->
  <Target Name="CleanUnreferenceProjectOutput" BeforeTargets="Clean">
    <ItemGroup>
    <!-- Removed the .dll from the end of this to clean up the pdbs  as well -->
      <SourceFiles Include="$(SolutionDir)\ClassLibrary1\$(OutputPath)*" />
      <SourceFiles Include="$(SolutionDir)\ConsoleApplication1\$(OutputPath)*.dll" />
    </ItemGroup>

    <Delete Files="@(SourceFiles)" />
  </Target>
</Project>

我认为这是最好的。你可以扩展它以获得一个未被引用但你想要构建的项目列表,但是对于这个例子我只是把它留在了一个。

编辑2:在开始解决当前的解决方案之前,我进行了大量的研究,在将程序集解析之前将引用注入ProjectReference项目组。可以这样做,但是你必须将属性BuildInVisualStudio设置为false,否则当ResolveProjectReferencesMicrosoft.Common.Current.targets目标中的msbuild条件被评估时,你将选择一个只运行该命令的MSBuild任务GetManifest目标。我能够获得构建解决方案,但鉴于我对BuildInVisualStudio设置为false的缺乏知识,我选择了上面的解决方案。另外,我添加了一个清理移动到bin文件夹的文件的任务,因为clean只会清理项目的obj文件夹中的{ProjectName}{ProjectExtension}FileListAbsoluteText.txt

编辑:在对下面的解决方案进行更多研究之后,它只能在命令行中运行。我目前正在研究为什么会这样。