项目项元数据 "PreserveNewest" 是如何工作的?

How does project item metadata "PreserveNewest" actually work?

在我的 .csproj 文件中,我添加了以下配置:

<ItemGroup>
    <None Include="$(USERPROFILE)\.nuget\packages\microsoft.data.sqlclient.sni.0.19235.1\buildTransitive\net46\x64\SNI.dll">
        <!-- This is a workaround to include SNI.dll in the NuGet package resulting from the pipeline in Azure DevOps. -->
        <Link>x64\SNI.dll</Link>
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
</ItemGroup>

但是,很难找到关于 PreserveNewest 实际工作原理的文档。我查看了各种 Whosebug 帖子,发现 this page from the documentation,它在 None 元素的部分下说明:

CopyToOutputDirectory Optional string. Determines whether to copy the file to the output directory. Values are:

  1. Never
  2. Always
  3. PreserveNewest

它并没有真正描述它是如何工作的。有人知道吗?它根据什么标准决定什么是最新的?文件更改日期?其他版本元数据? “保留”是什么意思?

配置的目的是将 SNI.dll 文件复制到 bin/x64 目录,它成功完成了。

它基于文件修改时间戳。即使查看 the responsible source code 也有点模糊,因为 MSBuild 使用 Inputs/Outputs 个目标来确定是否需要执行部分构建逻辑。

因此,如果您修改磁盘上的源文件,下一个 MSBuild 运行 会将时间戳与输出目录中预期文件的时间戳进行比较,并且仅在目标文件丢失时才执行该逻辑或具有相同或更新的修改日期。

这意味着最好是 select PreserveNewest 如果您不希望目标目录中的文件发生更改(例如,在应用程序启动时修改的数据库文件) Always 有两个原因:

  • 复制可能较大的文件所需的磁盘 IO 较少
  • 如果 VS Project 系统将任何项目设置为 Always,则它不会将项目视为“最新”——这意味着 VS 中的“Build”/“运行”将始终调用 MSBuild如果它知道没有文件发生变化,则不会跳过项目。

请注意,您需要的一个选项 - CopyIfDifferent - 不存在。因此,如果您使用 PreserveNewest,例如回滚您的 VCS 历史记录,您最终可能会使用错误的文件。