我想在 C# 构建期间运行脚本,但**仅**当项目不是最新时运行

发布于 2024-09-16 12:27:17 字数 1055 浏览 9 评论 0原文

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

要求是:

  1. 仅当组件不是最新时才构建组件。 (Visual Studio 中和通过 MSBuild 的正常行为)
  2. 构建程序集后,将获取分配的正确版本。

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

如果项目是最新的并且没有触发构建,则预构建事件不会运行。

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

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

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

有人建议如何在项目不是最新的情况下**仅*运行脚本吗?

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

I am trying to set up a proper way to do automatic versioning for my C# projects in .Net.

The requirements are:

  1. the assembly is to be built only when is is not up to date. (normal behaviour in Visual Studio and via MSBuild)
  2. When it is built the assembly is to get the proper version assigned.

I have found a solution to give me the version-strings I want. However, to make the assemblies reflect this version after build I need to change the assemblyInfo.cs file just before it is being built. I ended up enabling this functionality via adding a script to be run on the pre-build event. According to Microsoft documentation this should be fine:

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

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

This is so not true! Pre-build event scripts always execute - even if the project is up to date! That is. The pre-build script is run, even when it doesn't recompile (since it is up-to-date). Since my script updates the assemblyInfo.cs file the project is no longer up-to-date so it recompiles (due to a bug/designflaw I had to add the directive to disable caching). This means that the project recompiles every time, which is of course not what I want - considering that I have 103 projects in my solution...

I have investigated this further by adding both BeforeBuild and BeforeCompile targets in the project-file. Guess what: They also run every time even if the project is up-to-date. I have tried running the build from both Visual Studio and from MSBuild with the same sad results.

Does anybody have a suggestion on how to have scripts run **only* when the project is not up to date?

BTW: Before it is suggested:
I have reviewed most solutions available on the net, including automatic increments via the "1.*" specifier in assemblyInfo.cs. This is not what I want. My versioning needs are somewhat more complex.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心欲静而疯不止 2024-09-23 12:27:17

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

在调查 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>

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

It doesn't seem anyone had a solution on this, but with extra investigation I was finally able to find a workaround.

After investigating the Microsoft.CSharp.targets file I found that there are no "hooks" in CoreCompile that call targets only when CoreCompile is run. CoreCompile itself depends on comparison of Inputs and Outputs to determine whether it should run or not. Armed with that information I copied the input and output specifications from CoreCompile and voila :)

My custom BeforeCompile task now like this:

<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>

It looks a bit kludgy, but it works. The inputs and outputs are probably also fairly safe to copy. Can't see any good reason for Microsoft to change them often ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文