3

我正在尝试为.Net 中的 C# 项目设置正确的方法来进行自动版本控制。

要求是:

  1. 只有当它不是最新的时,才会构建程序集。(在 Visual Studio 中和通过 MSBuild 的正常行为)
  2. 当它被构建时,程序集将获得分配的正确版本。

我找到了一个解决方案来给我想要的版本字符串。但是,为了使程序集在构建后反映此版本,我需要在构建之前更改 assemblyInfo.cs 文件。我最终通过添加要在预构建事件上运行的脚本来启用此功能。根据 Microsoft 文档,这应该没问题:

Pre-build events do not run if the project is up to date and no build is triggered.

(参考: http: //msdn.microsoft.com/en-us/library/42x5kfw4.aspx):

这太不真实了!预构建事件脚本始终执行 - 即使项目是最新的!那是。预构建脚本会运行,即使它没有重新编译(因为它是最新的)。由于我的脚本更新了 assemblyInfo.cs 文件,因此项目不再是最新的,因此它会重新编译(由于错误/设计缺陷,我不得不添加指令以禁用缓存)。这意味着项目每次都会重新编译,这当然不是我想要的——考虑到我的解决方案中有 103 个项目......

我通过在项目文件中添加 BeforeBuild 和 BeforeCompile 目标进一步调查了这一点。猜猜看:即使项目是最新的,它们也会每次都运行。我尝试从 Visual Studio 和 MSBuild 运行构建,但结果相同。

当项目不是最新的时,是否有人对如何让脚本运行**仅*有建议?

顺便说一句:在建议之前: 我已经查看了网络上可用的大多数解决方案,包括通过 assemblyInfo.cs 中的“1.*”说明符自动递增。这不是我想要的。我的版本控制需求稍微复杂一些。

4

1 回答 1

2

似乎没有人对此有解决方案,但经过额外调查,我终于找到了解决方法。

在调查 Microsoft.CSharp.targets 文件后,我发现 CoreCompile 中没有“钩子”,仅在运行 CoreCompile 时才调用目标。CoreCompile 本身依赖于输入和输出的比较来确定它是否应该运行。有了这些信息,我从 CoreCompile 复制了输入和输出规范,瞧 :)

我的自定义 BeforeCompile 任务现在是这样的:

<Target
  Name="BeforeCompile"
  Inputs="$(MSBuildAllProjects);
          @(Compile);                               
          @(_CoreCompileResourceInputs);
          $(ApplicationIcon);
          $(AssemblyOriginatorKeyFile);
          @(ReferencePath);
          @(CompiledLicenseFile);
          @(EmbeddedDocumentation); 
          $(Win32Resource);
          $(Win32Manifest);
          @(CustomAdditionalCompileInputs)"
  Outputs="@(DocFileItem);
           @(IntermediateAssembly);
           @(_DebugSymbolsIntermediatePath);                 
           $(NonExistentFile);
           @(CustomAdditionalCompileOutputs)">
  <Message Text="BeforeCompile (only when project is not up-to-date)"/>
</Target>

它看起来有点笨拙,但它确实有效。输入和输出的复制可能也相当安全。看不出微软经常更改它们的任何充分理由......

于 2010-09-06T15:10:59.707 回答