我有一个包含在多个解决方案中的ASP.NET项目。在每个解决方案中,我都希望将一个不同的未引用的项目包含在ASP.NET项目的构建输出中。解决方案如下所示:
Foo.sln
Bar.sln
理想情况下,即使使用F5进行调试,这也可以正常工作。我尝试使用构建配置执行此操作,但在Visual Studio中工作时,偏离典型的“调试”和“发布”似乎很脆弱。有没有一种典型的方法呢?
答案 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,否则当ResolveProjectReferences
中Microsoft.Common.Current.targets
目标中的msbuild条件被评估时,你将选择一个只运行该命令的MSBuild任务GetManifest
目标。我能够获得构建解决方案,但鉴于我对BuildInVisualStudio
设置为false的缺乏知识,我选择了上面的解决方案。另外,我添加了一个清理移动到bin文件夹的文件的任务,因为clean只会清理项目的obj文件夹中的{ProjectName}{ProjectExtension}FileListAbsoluteText.txt
。
编辑:在对下面的解决方案进行更多研究之后,它只能在命令行中运行。我目前正在研究为什么会这样。