20

在 Visual Studio 中,您可以执行Add-> Existing Item,然后Add as LinkAdd下拉按钮中执行。

这很棒。这让您可以从另一个项目中添加一个文件,并且编辑该文件也会在原始项目中对其进行编辑。

我想使用此功能在一个解决方案中的所有项目中都存在一个配置文件(名为 Shared.config)。并让该文件始终相同。

解决方案
|
|- 项目一
| - Shared.config [物理]
|- 项目 2
| - Shared.config [链接]

发布后,该文件确实会出现在所有已发布的项目中,所以没有问题。

但是在发布之前(在构建开发期间)链接文件并不真正存在。尝试在 Windows 资源管理器中查看该文件证明该文件不在项目目录中。Visual Studio 只是让它看起来好像它存在于解决方案资源管理器中。(虽然在构建时,链接的项目可能被复制到bin目录中;但我不想使用/访问目录中的bin文件。)

现在,这会产生问题。在项目发布之前尝试打印System.IO.File.ReadAllText(HttpContext.Current.Server.MapPath("Shared.config"))会失败,因为 Shared.config 尚不存在于项目根目录中。

我想做的,我需要你帮助的地方是:

  • 我想 ON BUILD 将所有链接文件从原始位置复制到目标位置。

这将使 Visual Studio 拥有链接文件和原始文件的副本,以相同的名称存在于同一目录中。

通常,如果该目录已包含同名文件,VS 将不允许您在该目录中创建链接项。

但是,我首先通过创建链接项目进行了测试;然后使用 Windows 资源管理器将原始文件复制到目标目录,并查看 Visual Studio 是否正常。解决方案资源管理器只是隐藏了物理文件,而是显示了链接的项目。(即使您单击Show all files解决方案资源管理器。)

解决方案
|
|- 项目一
| - Shared.config [物理]
|- 项目 2
| - Shared.config [链接]
| - Shared.config [物理的,在构建期间复制到这里,对解决方案资源管理器不可见]

这正是我想要的!尝试编辑文件时,Visual Studio 将打开“链接项目”。并且在构建时,一个物理文件将被复制到目标目录,因此它存在于试图访问它的代码中。

现在我该怎么做?这应该通过 Build 事件来完成吗?如果是这样,我怎么说'将所有链接文件的原件复制到它们的目标目录?

4

4 回答 4

27

我对dss539 的回答有些麻烦(在 vs2010 中测试)。首先,解决方案资源管理器中出现每个匹配文件的重复项。其次,'%link'它不是属性访问器,它是字符串本身,并且它始终不等于空字符串'',因此每个具有None构建操作的文件都在构建时被匹配、复制和复制。第三,链接文件正在复制到项目的根目录中,但我需要将文件复制到放置链接的位置。所以我做了一些修改:

<Target Name="CopyLinkedFiles" BeforeTargets="Build">
  <ItemGroup>
    <LinkedItem Include="@(Content)" Condition="%(Content.Link) != ''" />
  </ItemGroup>
  <Copy SourceFiles="@(LinkedItem)" DestinationFiles="%(LinkedItem.Link)"/> 
</Target>

LinkedItem不再重复解决方案资源管理器中的项目。要复制链接,您必须设置Content构建操作。

于 2013-07-02T14:59:07.743 回答
17

您可能应该使用 MSBuild 功能来实现这一点。

编辑 csproj 文件(在 Visual Studio 中,右键单击项目并卸载它。然后右键单击并编辑)

滚动到底部,您应该会找到这一行。

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

在该行之后,立即添加这些行。

  <ItemGroup>
    <LinkedItem Include="@(None)" Condition="'%Link' != ''" />
  </ItemGroup>
  <Target Name="CopyLinkedFiles" BeforeTargets="Build" Inputs="@(LinkedItem)" Outputs="@(LinkedItem->'%(Filename)%(Extension)')">
    <Copy SourceFiles="@(LinkedItem)" DestinationFolder="$(MSBuildProjectDirectory)" />
  </Target>

现在,每次构建时,在构建操作发生之前,MSBuild 都会复制所有链接的文件。

解释

ItemGroup包含我的名为“LinkedItem”的“数组”。我通过仅添加包含链接属性的“无”项来生成此数组。

Target是一个 MSBuild 概念。您可以将其视为构建的特定阶段。我将此阶段命名为“CopyLinkedFiles”,但您可以将其命名为任何名称。

BeforeTargets是一个指令,它告诉 MSBuild 在指定阶段之前运行操作。在这里,我选择在“构建”阶段之前运行“CopyLinkedFiles”。

Inputs是优化参数。如果不需要,它用于通过跳过副本来加快构建速度。如果你不关心,你可以忽略这个参数。MSBuild 将Inputs与预期Outputs时间戳进行比较以查看它是否需要执行。

Copy是一个 MSBuild 任务,它接受要复制的文件并输出到指定文件夹。

减少冗余

您可以将其粘贴到每个 .csproj 文件中,也可以将其放在中央 .proj 中并将其嵌入到 csproj 文件中。可悲的是,无论您做什么,您都必须编辑每个 .csproj 至少 1 次。:(

在 Common 项目调用中创建文件WhateverNameYouLike.proj 将这些内容放入文件中。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- paste the previously shown code here -->

  <!-- you can save yourself some hassle by linking the config file here, but if you really enjoy adding the file as a link to every project, you can skip this line -->
  <None Include="..\Common\Shared.config">
    <Link>Shared.config</Link>
  </None>
</Project>

现在烦人的部分:在每个 .csproj 中,您必须 在结束标记<Import Project="..\Common\WhateverNameYouLike.proj" /> 之前添加一行,例如可能在结尾处。</Project>

于 2013-03-19T17:25:02.853 回答
1

右键单击链接的配置文件,选择属性,Copy to Output Directory从更改NeverCopy always.

于 2013-03-19T17:12:57.123 回答
0

您可以在 Visual Studio 中创建构建前和构建后事件。

选择项目,右键单击,属性,构建事件。

对于预建 -

copy /y "$(LocationOfShared.Config)Shared.config\" "$(TargetDir)"

对于后期构建

cd $(TargetDir)
del shared.config

显然,您需要使用将要返回的实际位置,但您明白了。

编辑 - 上面的答案更容易和直接,但这应该作为一种循环方式来工作。

于 2013-03-19T17:13:05.287 回答