我可以将 Visual Studio 中“复制本地”的默认选项设置为 False 吗?在大多数情况下,当我添加一个 dll 作为项目的依赖项时,我希望将 Copy Local 属性设置为 False。默认情况下,它是 True。有没有办法改变 Visual Studio 的默认行为?(2008)
6 回答
否 - Visual Studio 使用一组内部规则来确定将“本地复制”设置为的内容。
来自MSDN:
- 如果引用是另一个项目,称为项目到项目引用,则值为true。
- 如果在全局程序集缓存中找到程序集,则值为false。
- 作为一种特殊情况,mscorlib.dll 引用的值为false。
- 如果在 Framework SDK 文件夹中找到程序集,则值为false。
- 否则,值为true。
事实上,你可以。你需要几件事:
- 创建默认情况下
.targets
使 copylocal(<Private>
准确地说是标签)为false 的文件。 .csproj
在文件中导入目标。您可以在最后一行添加它,在结束</Project>
标记之前,它看起来像<Import Project="..\Build\yourtarget.targets" />
.
现在,每个具有此目标的项目都默认禁用了 copylocal。
缺点是您需要修改每个 csproj 文件,包括新文件。您可以通过修改 VS 项目模板来解决新项目问题。Class.cs
您需要修改Class.vstemplate
(在同一个 zip 文件中) ,而不是在博客文章中描述。
使用这种方法,还有一个问题 - 路径本身。如果你在新生成的 csproj 文件中使用硬编码的相对路径,它们可能是错误的(除非你有扁平的项目结构)。
你可以:
- 让 VS 生成正确的相对路径。不知道如何做到这一点,如果这甚至可能。
- 忽略它并为每个新的 csproj 手动更改路径(取决于您拥有的新项目的数量,虽然不理想,但可能是可以容忍的)。
- 使用环境变量而不是相对路径。在这种情况下,每个开发人员都需要相同的变量集。
必须有更好的解决方案,但还没有找到。
从 msbuild v 15 开始,您可以在包含源代码的根文件夹中复制一个名为Directory.Build.props的文件:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemDefinitionGroup>
<Reference>
<Private>False</Private>
</Reference>
<ProjectReference>
<Private>False</Private>
</ProjectReference>
</ItemDefinitionGroup>
</Project>
无事可做!这适用于 Visual Studio 2017 以及 vNext Build。您可能必须关闭 Visual Studio 并再次打开您的解决方案才能使文件生效。
我们不使用 .targets 文件(正如 ya23 的回答中所建议的那样),因此我们只需.csproj
在文本编辑器中手动编辑项目文件并将<Private>
元素添加到引用中,如下所示:
<Reference Include="[...]">
<Private>False</Private>
[...]
</Reference>
元素的<Private>
值与“复制本地”属性的值相匹配。例如,如果<Private>
设置为 False,则“复制本地”也是错误的。
关于@herzbube 发布的解决方案,如果您想为.csproj文件中的所有(或大部分)引用关闭“复制本地”,则无需<Private>False</Private>
在每个上单独设置Reference
,只需输入以下内容直接在.csproj中:
<ItemDefinitionGroup>
<Reference>
<Private>False</Private>
</Reference>
</ItemDefinitionGroup>
这不会影响用 引用的项目<ProjectReference>
,但您可以为这些项目做同样的事情 - 或者也可以这样做:
<ItemDefinitionGroup>
<ProjectReference>
<Private>False</Private>
</ProjectReference>
</ItemDefinitionGroup>
如果你想要这两个,你可以将它们合并到一个组中:
<ItemDefinitionGroup>
<Reference>
<Private>False</Private>
</Reference>
<ProjectReference>
<Private>False</Private>
</ProjectReference>
</ItemDefinitionGroup>
确保将这些覆盖放在第一个实际或要影响的覆盖之前,因为这些块仅适用于出现在它们下方的那些引用。然后,如果您确实希望在本地复制一些内容,您可以单独覆盖它们(即,在单个标签本身内),这次使用.<Reference … >
<ProjectReference … >
True
对于更高级的情况,您可以在同一个 .csproj 文件中多次在True和False之间来回切换覆盖值。另一种先进的技术是战略性地将您的一些参考放在这些块下方,而将其他参考放在上面,这样后者就不会受到影响。
所有这些都应该使您的 .csproj 中的 XML 更加清晰易读。但还有更多好消息,请继续阅读......
至于选择哪些项目应该被标记,<Private>False</Private>
这通常取决于具体情况,但对于初学者来说,每个人都可以而且应该做一些基本的事情。这是一个如此基本、简单和有效的步骤,它提供了如此巨大的MSBuild可靠性改进1.和构建时间加速——几乎没有缺点——每个使用默认(即每个项目的本地)C#输出位置的大型解决方案应该几乎总是进行这种调整:
在任何一个 Visual Studio 解决方案中,该解决方案构建了具有任何重要数量的相互依赖关系的多个 C#类库,并最终构建了一个更多的应用程序(即可执行文件):
<ProjectReference>
在每个类库的 .csproj 顶部附近,插入
<ProjectReference>
上面显示的块。
原因:任何.dll都不需要将它引用的任何库收集到它自己的子目录中,因为从该位置没有运行任何可执行文件。这种猖獗的复制是无用的忙碌工作,可能会不必要地减慢您的构建速度,可能会非常显着。另一方面,不要为任何解决方案的应用程序修改 .csproj 。
原因:可执行文件需要在其各自的子目录中拥有所有他们需要的私有库,但是每个应用程序的构建应该负责单独收集每个依赖项,直接从其各自的子目录到应用程序的子目录中目录。
这非常有效,因为类库的 .csproj 可能会引用多个其他类库,但可执行文件的 .csproj 通常从不引用另一个可执行文件。因此,对于每个本地构建的库,其文件夹中唯一的.dllbin
将是它自己,而每个本地构建的应用程序都将包含它引用的完整的本地构建库集。
方便的是,对于不是由您的解决方案构建的引用库,没有任何变化,因为它们通常使用<Reference>
而不是<ProjectReference>
,并且我们根本没有修改前一个标记。但请注意刚才提到的假设;如果您的某些项目违反了它,您可能需要进行一些调整。
[1.] 可靠性改进可能与从依赖图中的多个不相交路径收集相同库时可能发生的文件冲突有关,尤其是在并发构建中。