作者: zyl910

一、缘由

当创建 .NET Core/Standard 2.0项目时,VS不会像.NET Framework项目一样自动生成AssemblyInfo.cs文件。

而且,若是手工在项目中加入以前写好的 AssemblyInfo.cs 文件,编译时会报告“CS0579: Duplicate 'AssemblyFileVersionAttribute' attribute”错误。

查了一下资料,发现是因为“.NET Core/Standard 2.0会自动填写程序集信息”而引起的。

具体来说——

  1. .NET Core/Standard 2.0 推荐在项目属性的“Package”页配置程序集的 版本、描述 等信息。
  2. 编译时,会自动根据“Package”页的配置,生成 “<项目名>.AssemblyInfo.cs”。其中便使用了 AssemblyFileVersionAttribute 等特性。
  3. 我们的 AssemblyInfo.cs 中也使用 AssemblyFileVersionAttribute 等特性。因为 AssemblyFileVersionAttribute 等特性是不允许重复,于是便报出CS0579错误了。

删除自己的 AssemblyInfo.cs,完全使用推荐做法(项目属性的“Package”页),当然是可以解决该问题、使项目能成功编译的。但是该方案的缺点是没有AssemblyInfo.cs,无法再用“利用条件编译控制程序集特性”等技巧。

第二种办法是在 AssemblyInfo.cs 中加上条件编译,若发现是 .NET Core/Standard 2.0(#if NETCOREAPP2_0 || NETSTANDARD2_0)时,便屏蔽掉 AssemblyFileVersionAttribute 等特性。但该方法比较繁琐。

有没有办法“禁止自动生成程序集特性,完全使用自己的AssemblyInfo.cs”呢?

二、解决

查了一下资料,找到了“.NET Core/Standard 2.0 禁止自动生成程序集特性”的办法。就是——修改项目的csproj文件,在PropertyGroup节点内加上“false”

例如修改前是这样的——

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

  <PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>ConsoleExample</AssemblyName>
<RootNamespace>ConsoleExample</RootNamespace>
</PropertyGroup> </Project>

修改后变为这样——

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

  <PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>ConsoleExample</AssemblyName>
<RootNamespace>ConsoleExample</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </Project>

改好后便会发现不再自动生成 “<项目名>.AssemblyInfo.cs”了,能使用自己的AssemblyInfo.cs,顺利编译了。

三、深入

3.1 自动生成的机制

“<项目名>.AssemblyInfo.cs”的内容一般是这样的——

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("ConsoleExample")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyDescriptionAttribute("Package Description")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("ConsoleExample")]
[assembly: System.Reflection.AssemblyTitleAttribute("ConsoleExample")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

上面这段自动生成的代码,实际上是由 c:\Program Files\dotnet\sdk\2.0.0\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.GenerateAssemblyInfo.targets 控制的。该文件的内容是——

<!--
***********************************************************************************************
Microsoft.NET.GenerateAssemblyInfo.targets WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE. Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
============================================================
GenerateAssemblyInfo Generates assembly info source to intermediate directory
============================================================
-->
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<GeneratedAssemblyInfoFile Condition="'$(GeneratedAssemblyInfoFile)' ==''">$(IntermediateOutputPath)$(MSBuildProjectName).AssemblyInfo$(DefaultLanguageSourceExtension)</GeneratedAssemblyInfoFile>
<GenerateAssemblyInfo Condition="'$(GenerateAssemblyInfo)' == ''">true</GenerateAssemblyInfo>
</PropertyGroup> <PropertyGroup Condition="'$(GenerateAssemblyInfo)' == 'true'">
<GenerateAssemblyCompanyAttribute Condition="'$(GenerateAssemblyCompanyAttribute)' == ''">true</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyConfigurationAttribute Condition="'$(GenerateAssemblyConfigurationAttribute)' == ''">true</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCopyrightAttribute Condition="'$(GenerateAssemblyCopyrightAttribute)' == ''">true</GenerateAssemblyCopyrightAttribute>
<GenerateAssemblyDescriptionAttribute Condition="'$(GenerateAssemblyDescriptionAttribute)' == ''">true</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyFileVersionAttribute Condition="'$(GenerateAssemblyFileVersionAttribute)' == ''">true</GenerateAssemblyFileVersionAttribute>
<GenerateAssemblyInformationalVersionAttribute Condition="'$(GenerateAssemblyInformationalVersionAttribute)' == ''">true</GenerateAssemblyInformationalVersionAttribute>
<GenerateAssemblyProductAttribute Condition="'$(GenerateAssemblyProductAttribute)' == ''">true</GenerateAssemblyProductAttribute>
<GenerateAssemblyTitleAttribute Condition="'$(GenerateAssemblyTitleAttribute)' == ''">true</GenerateAssemblyTitleAttribute>
<GenerateAssemblyVersionAttribute Condition="'$(GenerateAssemblyVersionAttribute)' == ''">true</GenerateAssemblyVersionAttribute>
<GenerateNeutralResourcesLanguageAttribute Condition="'$(GenerateNeutralResourcesLanguageAttribute)' == ''">true</GenerateNeutralResourcesLanguageAttribute>
</PropertyGroup> <!--
Note that this must run before every invocation of CoreCompile to ensure that all compiler
runs see the generated assembly info. There is at least one scenario involving Xaml
where CoreCompile is invoked without other potential hooks such as Compile or CoreBuild,
etc., so we hook directly on to CoreCompile. Furthermore, we must run *after*
PrepareForBuild to ensure that the intermediate directory has been created.
-->
<Target Name="GenerateAssemblyInfo"
BeforeTargets="CoreCompile"
DependsOnTargets="PrepareForBuild;CoreGenerateAssemblyInfo"
Condition="'$(GenerateAssemblyInfo)' == 'true'" /> <Target Name="GetAssemblyAttributes"
DependsOnTargets="GetAssemblyVersion">
<ItemGroup>
<AssemblyAttribute Include="System.Reflection.AssemblyCompanyAttribute" Condition="'$(Company)' != '' and '$(GenerateAssemblyCompanyAttribute)' == 'true'">
<_Parameter1>$(Company)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyConfigurationAttribute" Condition="'$(Configuration)' != '' and '$(GenerateAssemblyConfigurationAttribute)' == 'true'">
<_Parameter1>$(Configuration)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyCopyrightAttribute" Condition="'$(Copyright)' != '' and '$(GenerateAssemblyCopyrightAttribute)' == 'true'">
<_Parameter1>$(Copyright)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyDescriptionAttribute" Condition="'$(Description)' != '' and '$(GenerateAssemblyDescriptionAttribute)' == 'true'">
<_Parameter1>$(Description)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyFileVersionAttribute" Condition="'$(FileVersion)' != '' and '$(GenerateAssemblyFileVersionAttribute)' == 'true'">
<_Parameter1>$(FileVersion)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyInformationalVersionAttribute" Condition="'$(InformationalVersion)' != '' and '$(GenerateAssemblyInformationalVersionAttribute)' == 'true'">
<_Parameter1>$(InformationalVersion)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyProductAttribute" Condition="'$(Product)' != '' and '$(GenerateAssemblyProductAttribute)' == 'true'">
<_Parameter1>$(Product)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyTitleAttribute" Condition="'$(AssemblyTitle)' != '' and '$(GenerateAssemblyTitleAttribute)' == 'true'">
<_Parameter1>$(AssemblyTitle)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyVersionAttribute" Condition="'$(AssemblyVersion)' != '' and '$(GenerateAssemblyVersionAttribute)' == 'true'">
<_Parameter1>$(AssemblyVersion)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Resources.NeutralResourcesLanguageAttribute" Condition="'$(NeutralLanguage)' != '' and '$(GenerateNeutralResourcesLanguageAttribute)' == 'true'">
<_Parameter1>$(NeutralLanguage)</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
</Target> <!--
To allow version changes to be respected on incremental builds (e.g. through CLI parameters),
create a hash of all assembly attributes so that the cache file will change with the calculated
assembly attribute values and msbuild will then execute CoreGenerateAssembly to generate a new file.
-->
<Target Name="CreateGeneratedAssemblyInfoInputsCacheFile"
DependsOnTargets="GetAssemblyAttributes">
<PropertyGroup>
<GeneratedAssemblyInfoInputsCacheFile>$(IntermediateOutputPath)$(MSBuildProjectName).AssemblyInfoInputs.cache</GeneratedAssemblyInfoInputsCacheFile>
</PropertyGroup> <Hash ItemsToHash="@(AssemblyAttribute->'%(Identity)%(_Parameter1)')">
<Output TaskParameter="HashResult" PropertyName="_AssemblyAttributesHash" />
</Hash> <WriteLinesToFile Lines="$(_AssemblyAttributesHash)" File="$(GeneratedAssemblyInfoInputsCacheFile)" Overwrite="True" WriteOnlyWhenDifferent="True" /> <ItemGroup>
<FileWrites Include="$(GeneratedAssemblyInfoInputsCacheFile)" />
</ItemGroup>
</Target> <Target Name="CoreGenerateAssemblyInfo"
Condition="'$(Language)'=='VB' or '$(Language)'=='C#'"
DependsOnTargets="CreateGeneratedAssemblyInfoInputsCacheFile"
Inputs="$(GeneratedAssemblyInfoInputsCacheFile)"
Outputs="$(GeneratedAssemblyInfoFile)">
<ItemGroup>
<!-- Ensure the generated assemblyinfo file is not already part of the Compile sources, as a workaround for https://github.com/dotnet/sdk/issues/114 -->
<Compile Remove="$(GeneratedAssemblyInfoFile)" />
</ItemGroup> <WriteCodeFragment AssemblyAttributes="@(AssemblyAttribute)" Language="$(Language)" OutputFile="$(GeneratedAssemblyInfoFile)">
<Output TaskParameter="OutputFile" ItemName="Compile" />
<Output TaskParameter="OutputFile" ItemName="FileWrites" />
</WriteCodeFragment>
</Target> <!--
==================================================================
GetAssemblyVersion Parses the nuget package version set in $(Version) and returns
the implied $(AssemblyVersion) and $(FileVersion). e.g.:
<Version>1.2.3-beta.4</Version> implies:
<AssemblyVersion>1.2.3</AssemblyVersion>
<FileVersion>1.2.3</FileVersion> Note that if $(AssemblyVersion) or $(FileVersion) are are already set, it
is considered an override of the default inference from $(Version) and they
are left unchanged by this target.
==================================================================
-->
<Target Name="GetAssemblyVersion">
<GetAssemblyVersion Condition="'$(AssemblyVersion)' == ''" NuGetVersion="$(Version)">
<Output TaskParameter="AssemblyVersion" PropertyName="AssemblyVersion" />
</GetAssemblyVersion> <PropertyGroup>
<FileVersion Condition="'$(FileVersion)' == ''">$(AssemblyVersion)</FileVersion>
<InformationalVersion Condition="'$(InformationalVersion)' == ''">$(Version)</InformationalVersion>
</PropertyGroup>
</Target> </Project>

3.2 部分自动生成

弄清楚机制后,我们可以做成部分自动生成的。即部分程序集特性自动生成,另外一部分来自我们自己的AssemblyInfo.cs。

具体办法是修改项目的csproj文件,在PropertyGroup节点内加上“false”等内容,而不用GenerateAssemblyInfo。

例如——

<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<OutputType>Exe</OutputType>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
</PropertyGroup>

GenerateAssemblyConfigurationAttribute这样的参数名详见 Microsoft.NET.GenerateAssemblyInfo.targets

参考文献

[C#] .NET Core/Standard 2.0 编译时报“CS0579: Duplicate 'AssemblyFileVersionAttribute' attribute”错误的解决办法的更多相关文章

  1. IIS7.5中调试.Net 4.0网站出现无厘头500错误的解决办法 (转)

    刚刚 部署了ii7的dll的有x86写的,就会出现以下这样的问题 iis 7 x86,Could not load file or assembly 'Name' or one of its depe ...

  2. ASP.NET CORE MVC 2.0 项目中引用第三方DLL报错的解决办法 - InvalidOperationException: Cannot find compilation library location for package

    目前在学习ASP.NET CORE MVC中,今天看到微软在ASP.NET CORE MVC 2.0中又恢复了允许开发人员引用第三方DLL程序集的功能,感到甚是高兴!于是我急忙写了个Demo想试试,我 ...

  3. Sublimetext (for windows)编译运行c出现Error 2错误的解决办法

      错误描述大概如下: [Error 2]  [cmd:  [u'bash', u'-c', u"g++ 'D:\\codeblocks\\project\\test.c' -o 'D:\\ ...

  4. Mysql8.0 Public Key Retrieval is not allow错误的解决办法

    在使用Mysql 8.0时重启后启动项目的事后会报错com.mysql.jdbc.exceptions.jdbc4.MysqlNonTransientConnectionException: Publ ...

  5. IDEA里运行代码时出现Error:scalac: error while loading JUnit4, Scala signature JUnit4 has wrong version expected: 5.0 found: 4.1 in JUnit4.class错误的解决办法(图文详解)

    不多说,直接上干货!  问题详情 当出现这类错误时是由于版本不匹配造成的 Information:// : - Compilation completed with errors and warnin ...

  6. Quartus ii 12.1软件破解之后编译原有的工程出现报警错误的解决办法

    在Quartus ii 12.1软件破解之后,想用来编译原来编译过的工程,但是编译到最后出现下面两个错误警告: 原来以为没有破解成功或者安装的时候有文件被杀毒软件吃了,导致安装错误,又重新安装了两次都 ...

  7. 数据库、ArcCatalog空间数据源正常访问,数据库设置没问题时,ArcEngine连接SDE时报"ORA-12560: TNS: 协议适配器错误"的解决办法;ArcEngine连接SDE总结

    碰到的问题描述: 通过C# 基于ArcEngine写SDE直连的时候测试项目连接属性设置为如下: tPropSet.SetProperty("User", "GISDAT ...

  8. EF6.0 Code First使用mysql的各种错误和解决办法!!

    1.修改或者添加connectionStrings <connectionStrings> <add name="MvcDBContext" connection ...

  9. VS2010出现FileTracker : error FTK1011编译错误的解决办法

    VS2010出现FileTracker : error FTK1011不知道是不是vs2010的一个bug,反正有人提交了. FileTracker : error FTK1011编译错误的解决办法有 ...

随机推荐

  1. js浮点数运算的坑,多少同学有碰到过?

    javascript中的数字都是双精度的浮点数. JavaScript中的整数并不是一个独立的数据类型,而是浮点数的一个子集. 浮点数的坑我们看下面的例子 在浏览器的console 控制台上我们分别进 ...

  2. [转]C++ 初始化列表的初始化顺序

    构造函数初始化列表仅用于初始化成员的值,并不指定这些初始化执行的次序.成员被初始化的次序就是定义成员的次序.第一个被定义的成员先被初始化,依次类推.一般,初始化的顺序无关紧要,然而,如果一个成员是根据 ...

  3. C语言程序设计(基础)- 第2周作业

    1.阅读提问的智慧,要求仔细阅读链接内容,用自己的话描述你的收获,并举例子说明应该如何提问. 2.所有同学请在自己电脑上配置git.编译器(win10 系统的话就Dev-C++).翻译软件,十一回校后 ...

  4. Beta No.3

    今天遇到的困难: 组员对github极度的不适应 github的版本控制和协同化编程确实操作起来需要一定的熟练度,我们缺乏这种熟练度 Android Studio版本不一致项目难以打开的问题仍然无法解 ...

  5. alpha-咸鱼冲刺day8

    一,合照 emmmmm.自然还是没有的. 二,项目燃尽图 三,项目进展 正在进行页面整合.然后还有注册跟登陆的功能完善-- 四,问题困难 数据流程大概是搞定了.不过语法不是很熟悉,然后还有各种判定. ...

  6. B-day5

    1.昨天的困难,今天解决的进度,以及明天要做的事情 昨天的困难:昨天虽然完成了风险数据的图表统计,但是界面风格仍然不太满意,还在抓紧调试中:还有登录页的背景图,在想应该如何设计, 什么样的风格才好. ...

  7. 201621123040《Java程序设计》第3周学习总结

    1.本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词,如类.对象.封装等 面向对象的思想 对象 类 1.2 用思维导图或者Onenote或其他工具将这些关键词组织起来. 掌握的还不够深 ...

  8. SUN平台服务器光纤共享存储互斥失败如何恢复数据?

    服务器数据恢复故障描述: 服务器最初的设计思路为将两台SPARC SOLARIS系统通过光纤交换机共享同一存储作为CLUSTER使用,正常情况下A服务器工作,当A服务器发生故障宕机后即可将其关机然后开 ...

  9. NFC驱动调试

    1.NFC基本概念: NFC 又称为近场通信,是一种新兴技术,可以在彼此靠近的情况下进行数据交换,是由非接触式射频识别(RFID) 及互连互通技术整合演变而来,通过单一芯片集成感应式读卡器: NFC有 ...

  10. typescript简介

    微软作为编译器狂魔一直有一个心病,就是改良JavaScript这种语法超级烂又很多人用的编程语言,于是TypeScript诞生了 先做个对比吧:   TS JS 语法严谨性 严谨 宽松 静态性 静态 ...