在Visual Studio 2022中,项目相关属性(如AssemblyInfo)应该存储在哪里?

huangapple go评论83阅读模式
英文:

Where should I store project related properties in visual studio 2022 ? (AssemblyInfo)

问题

I'm trying to understand where I should store data regarding the project that I might manually edit or programmaticaly change outside of execution of the project itself (ex: during build, after a git commit or after a nugetPackage deployement).

我正在尝试理解在项目执行之外的地方存储关于项目的数据,这些数据可能需要手动编辑或以编程方式更改(例如:在构建过程中、在 git 提交之后或在 nugetPackage 部署之后)。

A concrete exemple would be to manage version numbers.

一个具体的示例是管理版本号。

I would like to create 4 variable, that would be used to set the $(VersionPrefix) :

  • Major (manually updated)
  • Minor (manually updated)
  • LastGitHash (After git push)
  • BuildNumber (Incremented at each build, reset at new git push)

我想创建 4 个变量,用于设置 $(VersionPrefix):

  • Major(手动更新)
  • Minor(手动更新)
  • LastGitHash(在 git 提交后更新)
  • BuildNumber(每次构建时递增,新的 git 提交时重置)

It seems it used to be done in some way in AssemblyInfo but that it is deprecated.

似乎以前在 AssemblyInfo 中以某种方式完成,但现在已不推荐使用。

I could add a custom file somewhere... but there are probably more standard solutions...
I found Resources.resx as there is a link from the project Properties, it seems it could be the solution i'm looking for but I've not found the way to access those variables at build.

我可以在某个地方添加一个自定义文件... 但可能还有更标准的解决方案...
我发现 Resources.resx,因为在项目属性中有一个链接,看起来可能是我寻找的解决方案,但我还没有找到在构建过程中访问这些变量的方法。

英文:

I'm trying to understand where I should store data regarding the project that I might manually edit or programmaticaly change outside of execution of the project itself (ex: during build, after a git commit or after a nugetPackage deployement).

A concrete exemple would be to manage version numbers.

I would like to create 4 variable, that would be used to set the $(VersionPrefix) :

  • Major (manually updated)
  • Minor (manually updated)
  • LastGitHash (After git push)
  • BuildNumber (Incremented at each build, reset at new git push)

It seems it used to be done in some way in AssemblyInfo but that it is deprecated.

I could add a custom file somewhere... but there are probably more standard solutions...
I found Resources.resx as there is a link from the project Properties, it seems it could be the solution i'm looking for but I've not found the way to access those variables at build.

答案1

得分: 1

以下是翻译好的代码部分:

# 更新:

我的项目结构:

[![在这里输入图片描述][1]][1]

# 原始答案:

首先,项目相关的属性应该存储在.csproj文件的Property元素中,如下所示:

    <Project Sdk="Microsoft.NET.Sdk">

      <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <IncludeBuildOutput>true</IncludeBuildOutput>
        <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
        <major>1</major>
        <minor>1</minor>
        <patch>2</patch>
        <LastGitHash>0</LastGitHash>
        <BuildNumber>0</BuildNumber>
        <Version>$(major).$(minor).$(patch)</Version>
      </PropertyGroup>
    
      <!--输出消息-->
      <Target Name="OutputMessage" AfterTargets="Build">
        <Message Importance="high" Text="Version: $(Version)" />
      </Target>
    </Project>

**1, 主要版本和次要版本。**

> 主要版本(手动更新)

> 次要版本(手动更新)

对于这些要求,您可以使用msbuild命令来替换内容,如下所示:

`msbuild NET6_AssemblyInfo.csproj /p:major=2 /p:minor=2 /t:OutputMessage`

您还可以手动编辑.csproj文件中这两个设置的值。

**2, LastGitHash(在git推送之后)**

对于这一要求,您可以使用git钩子来满足要求:

查看官方文档。

[Git钩子](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)

您可以使用"post-receive"钩子。

以上是自动方法。

如果您在服务器上没有足够的权限,那么以上方法无法满足要求(因为post-receive是服务器端钩子,没有本地主机来满足您的要求)。 您需要编写脚本来更改值。

请参阅有关更改值的下面步骤。

**3, BuildNumber(在每次构建时递增,在新的git推送后重置)**

对于这一要求,您可以使用构建后事件来运行脚本,以在构建后更改文件的内容,并在新的git推送后调用脚本。

我将编写PowerShell脚本来满足您的要求。

**1'' 每次构建时递增:**

**change_value.ps1**

    #查找.csproj文件
    $csproj_file = Get-ChildItem -Path . -Filter *.csproj
    $csproj_file
    
    #从xxx.csproj读取XML内容
    $csproj = [xml](Get-Content $csproj_file)
    
    #获取属性的值
    $BN = $csproj.Project.PropertyGroup.BuildNumber
    
    $LGH
    $BN
    
    #递增BN的值
    $BN = [int]$BN + 1
    
    #在.csproj文件中替换BN的值
    $csproj.Project.PropertyGroup.BuildNumber = [string]$BN
    
    #保存.csproj文件
    $csproj.Save($csproj_file)

您可以将此PowerShell文件设置在此位置:

右键单击项目,点击属性:

[![在这里输入图片描述][2]][2]

[![在这里输入图片描述][3]][3]

当然,在上述步骤之前,您需要在环境变量中配置powershell.exe的根路径:

[![在这里输入图片描述][4]][4]

然后,构建操作将自动递增构建号:

[![在这里输入图片描述][5]][5]

**2'' 在新的git推送后重置**

如果您不需要在git推送后执行操作,您可以使用git钩子"pre-push"。

前往您的本地项目,然后点击.git->hooks,然后创建一个名为"pre-push"的文件:

[![在这里输入图片描述][6]][6]

内容:

    #!/bin/sh
    
    powershell -File reset_value.ps1

**reset_value.ps1**

    #查找.csproj文件
    $csproj_file = Get-ChildItem -Path . -Filter *.csproj
    $csproj_file
    
    #从xxx.csproj读取XML内容
    $csproj = [xml](Get-Content $csproj_file)
    
    #获取属性的值
    $BN = $csproj.Project.PropertyGroup.BuildNumber
    
    $LGH
    $BN
    
    #重置BN的值
    $BN = 0
    
    #在.csproj文件中替换BN的值
    $csproj.Project.PropertyGroup.BuildNumber = [string]$BN
    
    #保存.csproj文件
    $csproj.Save($csproj_file)

然后构建号的内容将被重置:

[![在这里输入图片描述][7]][7]
[![在这里输入图片描述][8]][8]

----------

顺便说一句,如果您可以确保每次git推送步骤都成功完成,那么第二步也可以使用pre-push钩子。在您的情况下,pre-push和post-push是相同的。

请注意,这是对提供的代码的翻译,不包含问题的回答或其他内容。如果您需要进一步的翻译或解释,请提出具体的问题。

英文:

Update:

My project structure:

在Visual Studio 2022中,项目相关属性(如AssemblyInfo)应该存储在哪里?

Original Answer:

First, project related properties should be stored in the Property of .csproj like this:

&lt;Project Sdk=&quot;Microsoft.NET.Sdk&quot;&gt;
&lt;PropertyGroup&gt;
&lt;TargetFramework&gt;net6.0&lt;/TargetFramework&gt;
&lt;ImplicitUsings&gt;enable&lt;/ImplicitUsings&gt;
&lt;Nullable&gt;enable&lt;/Nullable&gt;
&lt;IncludeBuildOutput&gt;true&lt;/IncludeBuildOutput&gt;
&lt;GeneratePackageOnBuild&gt;True&lt;/GeneratePackageOnBuild&gt;
&lt;major&gt;1&lt;/major&gt;
&lt;minor&gt;1&lt;/minor&gt;
&lt;patch&gt;2&lt;/patch&gt;
&lt;LastGitHash&gt;0&lt;/LastGitHash&gt;
&lt;BuildNumber&gt;0&lt;/BuildNumber&gt;
&lt;Version&gt;$(major).$(minor).$(patch)&lt;/Version&gt;
&lt;/PropertyGroup&gt;
&lt;!--output message--&gt;
&lt;Target Name=&quot;OutputMessage&quot; AfterTargets=&quot;Build&quot;&gt;
&lt;Message Importance=&quot;high&quot; Text=&quot;Version: $(Version)&quot; /&gt;
&lt;/Target&gt;
&lt;/Project&gt;

1, Major and minor.

> Major (manually updated)

> Minor (manually updated)

For these requirement, you can use msbuild command to replace the content like this:

msbuild NET6_AssemblyInfo.csproj /p:major=2 /p:minor=2 /t:OutputMessage

Also you can manually edit the values of these two settings in the .csproj file.

2, LastGitHash (After git push)

For this requirement, you can use git hooks to achieve your requirement:

See the official document.

Git Hooks

You can use the hook 'post-receive'.

Above is the auto method.

If you don't have enough permission in the server, then above method is unable to achieve(Because post-receive is a Server-Side Hook, these doesn't have a local host to achieve your requirements.). You need write your script to change the value.

See the below step about changing the value.

3, BuildNumber (Incremented at each build, reset at new git push)

For this requirement, you can use post build event to run script after build to change the content of the file. And call script after new git push.

I will right powershell scripts to achieve your requirements.

1'' Incremented at each build:

change_value.ps1

#find the .csproj file
$csproj_file = Get-ChildItem -Path . -Filter *.csproj
$csproj_file
#read xml content from xxx.csproj
$csproj = [xml](Get-Content $csproj_file)
#get the value of the property
$BN = $csproj.Project.PropertyGroup.BuildNumber
$LGH
$BN
#increment the BN value
$BN = [int]$BN + 1
#replace the BN value in the .csproj file
$csproj.Project.PropertyGroup.BuildNumber = [string]$BN
#save the .csproj file
$csproj.Save($csproj_file)

You can set this powershell file in here:

right click project, click properties:

在Visual Studio 2022中,项目相关属性(如AssemblyInfo)应该存储在哪里?

在Visual Studio 2022中,项目相关属性(如AssemblyInfo)应该存储在哪里?

Of course, you need to configure the powershell.exe root path to the env vars before the above step:

在Visual Studio 2022中,项目相关属性(如AssemblyInfo)应该存储在哪里?

And then, build operation will auto increase the build number:

在Visual Studio 2022中,项目相关属性(如AssemblyInfo)应该存储在哪里?

2'' reset at new git push

If you don't need after git push, you can use git hook 'pre-push'.

Go to your local project, then click in .git->hooks, then create a file named 'pre-push':

在Visual Studio 2022中,项目相关属性(如AssemblyInfo)应该存储在哪里?

content:

#!/bin/sh
powershell -File reset_value.ps1

reset_value.ps1

#find the .csproj file
$csproj_file = Get-ChildItem -Path . -Filter *.csproj
$csproj_file
#read xml content from xxx.csproj
$csproj = [xml](Get-Content $csproj_file)
#get the value of the property
$BN = $csproj.Project.PropertyGroup.BuildNumber
$LGH
$BN
#reset the BN value
$BN = 0
#replace the BN value in the .csproj file
$csproj.Project.PropertyGroup.BuildNumber = [string]$BN
#save the .csproj file
$csproj.Save($csproj_file)

Then the content of the build number will be reset:

在Visual Studio 2022中,项目相关属性(如AssemblyInfo)应该存储在哪里?
在Visual Studio 2022中,项目相关属性(如AssemblyInfo)应该存储在哪里?


By the way, if you can make sure each git push step on your side is success, then the second step can also use pre-push hook. In your situation, pre-push and post-push are same.

答案2

得分: 1

有两种不同的“项目系统”依赖于 MSBuild 构建:'传统' 和 'SDK 样式'。SDK 样式是在 .Net Core/.Net 中引入的。

如果项目文件中的 'Project' 元素具有 'Sdk' 属性,那么该项目是 SDK 样式项目。鉴于项目是 C# 和 .Net 6,该项目很可能是 SDK 样式项目。

.NET SDK 项目的程序集属性和版本属性

程序集信息不过时,SDK 项目直接支持一组属性的程序集信息。请参阅 程序集属性属性

在 Windows 11 的文件资源管理器中,可执行文件的属性对话框的 '详细信息' 选项卡将显示 '文件版本',这是 AssemblyFileVersionAttribute,它是从 $(FileVersion) 属性设置的。 '产品版本' 是 AssemblyInformationalVersionAttribute,它是 $(InformationalVersion) 属性。

AssemblyVersionAttributeAssemblyFileVersionAttribute 预计将为 Version 类型。Version 具有格式 major.minor[.build[.revision]],除了'.' 分隔符外,不能包含非数字字符。 Version 类型早于 SemVer

只有 AssemblyInformationalVersionAttribute 可以包含 alpha 版本信息。

为更好地支持 SemVer,官方微软文档中有三个属性被“解释不足”:$(VersionPrefix)$(VersionSuffix)$(Version)$(VersionPrefix) 对应于 SemVar Backus-Naur 形式语法 中的 <version core>

这些属性是相互构建的。来自源代码:

<PropertyGroup Condition=" '$(Version)' == '' ">
    <VersionPrefix Condition=" '$(VersionPrefix)' == '' ">1.0.0</VersionPrefix>
    <Version Condition=" '$(VersionSuffix)' != '' ">$(VersionPrefix)-$(VersionSuffix)</Version>
    <Version Condition=" '$(Version)' == '' ">$(VersionPrefix)</Version>
</PropertyGroup>

$(InformationalVersion) 的默认值是 $(Version)

$(FileVersion)$(AssemblyVersion) 的默认值实际上是 $(VersionPrefix)

(请注意,git 哈希应该位于 $(VersionSuffix) 中。)

这些不同的属性可以被覆盖,覆盖的定义可以在导入到项目的单独文件中。

设置版本

主要版本和次要版本号可以存储在其自己的文件中,可以独立于任何其他文件进行修改。也可以设置 BuildNumber 的默认值。

例如,ProjectVersion.props 文件可以定义 $(Major)$(Minor) 的值。

<!-- ProjectVersion.props -->
<Project>
  <PropertyGroup>
    <Major Condition=" '$(Major)' == '' ">1</Major>
    <Minor Condition=" '$(Minor)' == '' ">0</Minor>
  </PropertyGroup>
</Project>

而不是修改项目,可以创建 Directory.Build.props 文件,如果存在,将自动导入。Directory.Build.props 可以导入定义主要版本和次要版本值的文件,例如 ProjectVersion.props 文件。

<!-- Directory.Build.props -->
<Project>
  <Import Project="$([MSBuild]::GetPathOfFileAbove('$(MSBuildThisFile)', '$(MSBuildThisFileDirectory)../'))" />

  <!-- 从包含项目的文件夹导入 ProjectVersion.props 文件(如果存在) -->
  <Import Project="$(MSBuildProjectDirectory)/ProjectVersion.props" Condition="Exists('$(MSBuildProjectDirectory)/ProjectVersion.props')" />
  <!-- 设置 SDK 版本属性 -->
  <PropertyGroup>
    <VersionPrefix Condition=" '$(Major)' != '' and '$(Minor)' != '' and '$(BuildNumber)' != '' ">$(Major).$(Minor).$(BuildNumber)</VersionPrefix>
    <VersionPrefix Condition=" '$(Major)' != '' and '$(Minor)' != '' and '$(BuildNumber)' == '' ">$(Major).$(Minor)</VersionPrefix>
    <VersionSuffix Condition=" '$(LastGitHash)' != '' ">$(LastGitHash)</VersionSuffix>
  </PropertyGroup>
</Project>

第一个 Import 将搜索目录树中的另一个 Directory.Build.props 文件,如果找到一个,则导入。这与问题无关,但这是一个好的做法。

第二个 Import 获取包含项目文件的目录中的 ProjectVersion.props 文件的内容。Directory.Build.props 文件可以跨多个项目共享,每个项目可以拥有自己的 ProjectVersion.props 文件。

$(VersionPrefix) 是基于 $(Major)$(Minor)$(BuildNumber) 设置的。

$(VersionSuffix) 基于 $(LastGitHash) 设置。

获取 BuildNumber 和 LastGitHash

$(BuildNumber)$(LastGitHash) 的值来自哪里?这些值与源代码无关,必须由构建系统提供并在构建项目时传递给 MSBuild。

原问题没有标识构建系统。

一些提示:

  • 项目不应了解版本控制系统。不要将源代码与版本控制系统耦合。不要在项目内部运行 git 命令。
  • 不要将构建状态存储在版本控制中。不要尝试在源文件中持久化构建号。在给定的构建中,源代码不应该被构建更改。构建应尽可能确定性,可重复和可分发。
  • 项目不应了解构建系统。
  • 无论使用何种构建系统,都需要了解版本控制系统,因为它需要克隆或拉取存储库来构建。它可以确定适当的修订标识符并将其传递给 MSBuild 供构建使用。可以使用 /p/property 选项来将值传递给 MSBuild;例如 /p:LastGitHash=1234
  • 同样,BuildNumber 是构建系统的产物,应该由构建系统确定并传递给 MSBuild。大多数构建系统支持用于实现递增构建号的计数器。
英文:

There are two different 'project systems' that build on MSBuild: 'legacy' and 'SDK style'. The SDK style was introduced with .Net Core/.Net.

If the Project element in the project file has an Sdk attribute, then the project is an SDK style project. Given that the project is C# and .Net 6, the project is highly likely an SDK style project.

.NET SDK project Assembly attribute and Version properties

Assembly Info is not deprecated and SDK projects directly support assembly info with a set of properties. See Assembly attribute properties.

In Windows 11 in the file explorer, the 'Details' tab of the properties dialog for an executable file will show 'File version' which is the AssemblyFileVersionAttribute, which is set from the $(FileVersion) property. 'Product version' is the AssemblyInformationalVersionAttribute, which is the $(InformationalVersion) property.

The AssemblyVersionAttribute and AssemblyFileVersionAttribute are expected to be of type Version. A Version has the format major.minor[.build[.revision]] and, with the exception of the '.' delimiter, cannot contain non-numeric characters. The Version type predates SemVer.

Only the AssemblyInformationalVersionAttribute can contain alpha version information.

To better support SemVer, there are three properties that are 'under-explained' in the official Microsoft documentation: $(VersionPrefix), $(VersionSuffix), and $(Version). $(VersionPrefix) corresponds to &lt;version core&gt; in the SemVar Backus–Naur Form Grammar.

These properties build from each other. From the source code:

  &lt;PropertyGroup Condition=&quot; &#39;$(Version)&#39; == &#39;&#39; &quot;&gt;
    &lt;VersionPrefix Condition=&quot; &#39;$(VersionPrefix)&#39; == &#39;&#39; &quot;&gt;1.0.0&lt;/VersionPrefix&gt;
    &lt;Version Condition=&quot; &#39;$(VersionSuffix)&#39; != &#39;&#39; &quot;&gt;$(VersionPrefix)-$(VersionSuffix)&lt;/Version&gt;
    &lt;Version Condition=&quot; &#39;$(Version)&#39; == &#39;&#39; &quot;&gt;$(VersionPrefix)&lt;/Version&gt;
  &lt;/PropertyGroup&gt;

The default value for $(InformationalVersion) is $(Version).

The default value for $(FileVersion) and $(AssemblyVersion) is effectively $(VersionPrefix).

(Note that a git hash would need to be in the $(VersionSuffix).)

These various properties can be overridden and the overriding definitions can be in separate files that are imported into the project.

Setting the Version

The Major and Minor version numbers can be stored in their own file that can be modified independently of any other file. A default for BuildNumber could also be set.

As an example, a ProjectVersion.props file may define the values of $(Major) and $(Minor).

&lt;!-- ProjectVersion.props --&gt;
&lt;Project&gt;
  &lt;PropertyGroup&gt;
    &lt;Major Condition=&quot; &#39;$(Major)&#39; == &#39;&#39; &quot;&gt;1&lt;/Major&gt;
    &lt;Minor Condition=&quot; &#39;$(Minor)&#39; == &#39;&#39; &quot;&gt;0&lt;/Minor&gt;
  &lt;/PropertyGroup&gt;
&lt;/Project&gt;

Instead of modifying the project, a Directory.Build.props file can be created which, if present, will be automatically imported. Directory.Build.props can import a file that defines the Major and Minor values, which in this example is the ProjectVersion.props file.

&lt;!-- Directory.Build.props --&gt;
&lt;Project&gt;
  &lt;Import Project=&quot;$([MSBuild]::GetPathOfFileAbove(&#39;$(MSBuildThisFile)&#39;, &#39;$(MSBuildThisFileDirectory)../&#39;))&quot; /&gt;

  &lt;!-- Import ProjectVersion.props from the folder containing the project if the file exists --&gt;
  &lt;Import Project=&quot;$(MSBuildProjectDirectory)/ProjectVersion.props&quot; Condition=&quot;Exists(&#39;$(MSBuildProjectDirectory)/ProjectVersion.props&#39;)&quot; /&gt;
  &lt;!-- Set SDK version properties --&gt;
  &lt;PropertyGroup&gt;
    &lt;VersionPrefix Condition=&quot; &#39;$(Major)&#39; != &#39;&#39; and &#39;$(Minor)&#39; != &#39;&#39; and &#39;$(BuildNumber)&#39; != &#39;&#39;&quot;&gt;$(Major).$(Minor).$(BuildNumber)&lt;/VersionPrefix&gt;
    &lt;VersionPrefix Condition=&quot; &#39;$(Major)&#39; != &#39;&#39; and &#39;$(Minor)&#39; != &#39;&#39; and &#39;$(BuildNumber)&#39; == &#39;&#39;&quot;&gt;$(Major).$(Minor)&lt;/VersionPrefix&gt;
    &lt;VersionSuffix Condition=&quot; &#39;$(LastGitHash)&#39; != &#39;&#39; &quot;&gt;$(LastGitHash)&lt;/VersionSuffix&gt;
  &lt;/PropertyGroup&gt;
&lt;/Project&gt;

The first Import will search up the directory tree for another Directory.Build.props file and import it if one is found. This is not related to the question but it a good practice.

The second Import gets the content of the ProjectVersion.props file from the directory that contains the project file. The Directory.Build.props file can be shared across multiple projects and each project can have its own ProjectVersion.props file.

$(VersionPrefix) is set based on $(Major), $(Minor), and $(BuildNumber).

$(VersionSuffix) is set based on $(LastGitHash).

Getting BuildNumber and LastGitHash

Where do the values of $(BuildNumber) and $(LastGitHash) come from? Those values are external to the source code and must be provided by the build system and passed to MSBuild when the project is built.

The original question doesn't identify the build system.

Some tips:

  • The 'project' should have no knowledge of the version control system. Don't couple the source code to the version control system. Don't run git commands from inside the project.
  • Don't store build state in version control. Don't try to persist a build number in a file in the source. Within a given build, the source should never be changed by the build. Builds should be as deterministic as possible, repeatable, and distributable.
  • The 'project' should have no knowledge of the build system.
  • Whatever build system is in use, will need to know the version control system because it will need to clone or pull the repo to build. It can determine an appropriate revision identifier and pass that to MSBuild for use within the build. The /p or /property option switch can be used to pass values into MSBuild; e.g. /p:LastGitHash=1234.
  • Likewise the BuildNumber is an artifact of the build system and should be determined by the build system and passed to MSBuild. Most build systems support counters for implementing incrementing build numbers.

huangapple
  • 本文由 发表于 2023年3月3日 18:53:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75626134.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定