C# 动态引用项目的生成配置
我有一个ASP.NET项目,它包含在多个解决方案中。在每个解决方案中,我希望ASP.NET项目的生成输出中包含不同的未引用项目。解决方案如下所示:C# 动态引用项目的生成配置,c#,visual-studio,visual-studio-2015,msbuild,C#,Visual Studio,Visual Studio 2015,Msbuild,我有一个ASP.NET项目,它包含在多个解决方案中。在每个解决方案中,我希望ASP.NET项目的生成输出中包含不同的未引用项目。解决方案如下所示: Foo.sln WebApp.csproj Foo.csproj Bar.sln WebApp.csproj Bar.csproj 理想情况下,即使在使用F5进行调试时,这也会起作用。我尝试使用构建配置来实现这一点,但在VisualStudio中使用时,偏离典型的“调试”和“发布”似乎很脆弱。有没有一种典型的方法可以做到这一点?我不知道是
- Foo.sln
- WebApp.csproj
- Foo.csproj
- Bar.sln
- WebApp.csproj
- Bar.csproj
理想情况下,即使在使用F5进行调试时,这也会起作用。我尝试使用构建配置来实现这一点,但在VisualStudio中使用时,偏离典型的“调试”和“发布”似乎很脆弱。有没有一种典型的方法可以做到这一点?我不知道是否有一种典型的方法可以满足您的要求(从IDE),但您可以通过编辑*.proj文件手动完成这一点 每个项目将发出输出(*.dll、*.exe、app.config等),并将其复制到$(OutputPath)属性中指定的文件夹(内部将使用OutDir属性)。如果要构建解决方案,您将拥有$(SolutionDir)属性以及$(SolutionName)。因此,您可以定义新的msbuild项目,该项目将被其他项目引用,并且您可以设置属性$(OutputPath),以便每个输出都将进入一个文件夹(称之为Common.props):
$(MSBuildThisFileDirectory)
默认名称
调试
$(SolutionDir)$(SolutionName)\bin\$(配置)
之后,您应该通过其他项目导入该项目-*.*proj(您应该指定项目的正确路径):
使用common$(OutputPath)属性将把您所有的二进制文件放在一个文件夹中-这将有助于解决您的任务。我不知道是否有一种典型的方法来实现您的要求(从IDE),但您可以通过编辑*.proj文件手动完成这一任务 每个项目将发出输出(*.dll、*.exe、app.config等),并将其复制到$(OutputPath)属性中指定的文件夹(内部将使用OutDir属性)。如果要构建解决方案,您将拥有$(SolutionDir)属性以及$(SolutionName)。因此,您可以定义新的msbuild项目,该项目将被其他项目引用,并且您可以设置属性$(OutputPath),以便每个输出都将进入一个文件夹(称之为Common.props):
$(MSBuildThisFileDirectory)
默认名称
调试
$(SolutionDir)$(SolutionName)\bin\$(配置)
之后,您应该通过其他项目导入该项目-*.*proj(您应该指定项目的正确路径):
使用common$(OutputPath)属性将把所有二进制文件放在一个文件夹中-这将有助于解决您的任务。免责声明:我认为这不是一个很好的主意,但似乎可以做到。 为了测试这个解决方案,我创建了两个项目。控制台应用程序1和类库1。ConsoleApplication1没有对ClassLibrary1的引用(在Visual Studio中可见),但从Visual Studio生成ConsoleApplication1时,它将生成ClassLibrary1.dll,然后将其复制到ConsoleApplication1的bin文件夹中 要导入目标文件,请继续并将此行添加到要生成未引用项目的项目中。此路径将相对于当前项目,因此在我的情况下,目标文件位于解决方案的根目录下。请确保在
行后添加此项,因为未引用。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,否则在Microsoft.Common.Current.targets
中的ResolveProjectReferences
目标中计算msbuild条件时,您将选择仅运行GetManifest
目标的msbuild任务。我能够得到要构建的解决方案,但由于我不知道将BuildInVisualStudio
设置为false需要什么,我选择了上面的解决方案。此外,我还添加了一个清理移动到bin文件夹中的文件的任务,因为clean只清理项目的obj文件夹中的{ProjectName}{ProjectExtension}FileListAbsoluteText.txt
编辑:在对下面的解决方案进行更多的研究之后,它将只在命令行中工作。我目前正在调查为什么会发生这种情况。免责声明:我认为这不是一个好主意,但似乎可以做到。 为了测试这个解决方案,我创建了两个项目。控制台应用程序1和类库1。ConsoleApplication1没有对ClassLibrary1的引用(在Visual Studio中可见),但从Visual Studio生成ConsoleApplication1时,它将生成ClassLibrary1.dll,然后将其复制到ConsoleApplication1的bin文件夹中 要导入目标文件,请继续并将此行添加到要生成未引用项目的项目中。此路径将与当前项目相关,因此在我的示例中,targe
<Import Project="..\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>