.NET Analyzer: Package Version vs Assembly Version - c#

As you can see in the following picture when you create a project of type Analyzer with Code Fix (.NET Standard) using VS 2017, in the properties tab of the project there is package version, assembly version and assembly file version.
Are those 3 versions related together or not? Also, as I make changes in the project how am I supposed to change the versions number? For instance, if I fix a bug, if I add a new rule, etc.

Are those 3 versions related together or not? Also, as I make changes in the project how am I supposed to change the versions number? For instance, if I fix a bug, if I add a new rule, etc.
Before answering this question, we need to know some info about the AssemblyVersionand AssemblyFileVersion.
Assembly Version: This is the version that .Net looks at during run-time for loading packages and finding types.
Assembly File Version: This defines the version reported by the OS to other applications like Windows Explorer.
You can see the Rémy van Duijkeren`s answer for some more details.
However, NuGet doesn’t use either of these. It uses a third versioning attribute: AssemblyInformationalVersion - the Product version of the assembly.
It uses this attribute because nothing else seems to care about it. The informational version isn’t used by the OS or by .Net, which means it’s available for NuGet to claim. But this versioning attribute was removed in the AssemblyInfo.cs file, because they don’t apply to semantic versioning.
When you are in the project of type Analyzer with Code Fix (.NET Standard) using VS 2017, those attributes settings has moved into the .csproj file. By default they don't show up but you can discover them from Visual Studio 2017 in the project properties Package tab:
Once saved those values can be found in MyProject.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<Version>1.2.3.4</Version>
<Authors>Author 1</Authors>
<Company>Company XYZ</Company>
<Product>Product 2</Product>
<PackageId>MyApp</PackageId>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion>
<NeutralLanguage>en</NeutralLanguage>
<Description>Description here</Description>
<Copyright>Copyright</Copyright>
<PackageLicenseUrl>License URL</PackageLicenseUrl>
<PackageProjectUrl>Project URL</PackageProjectUrl>
<PackageIconUrl>Icon URL</PackageIconUrl>
<RepositoryUrl>Repo URL</RepositoryUrl>
<RepositoryType>Repo type</RepositoryType>
<PackageTags>Tags</PackageTags>
<PackageReleaseNotes>Release</PackageReleaseNotes>
</PropertyGroup>
In the file explorer properties information tab, Version is shown as "Product version", which is used by NuGet. Just like the versioning attribute: AssemblyInformationalVersion.
So, if you fix a bug or add a new rule, you can change the package version for shipping new package.
major is incremented for a breaking change, minor for a change that
is backwards compatible and patch for bug fixes.
As to whether it needs to be modified the versions number for Assembly Versions, you can refer to this document for some more details.
Hope this helps.

Related

Using MSBuild at command-line to produce VSIX does not error, does not build VSIX - but IDE does. How to debug?

I have a VSIX extension which I have migrated to a new solution (basically to remove older projects targeting older VS versions no longer supported by my company) and to simplify the codebase for ease of maintenance.
Within the IDE, it does not matter if I set the active configuration to Debug|x86 or Release|x86, it will build a VSIX artifact OK. All good so far.
If I use
MSBuuild /t:Build /p:Configuration=Release /p:Platform=x86 -restore -detailedSummary MyExtension.sln
it will build without any errors, but no VSIX is produced.
I have poured over the terminal output and there are no warnings/errors and the DLL output of projects in the solution are produced.
I did read the following:
Project not selected to build for this solution configuration
The option to click deploy from the above link is not available for my VSIX - all the deploy options are disabled.
I have searched S.O. for similar issues regarding a VSIX not being produced, but none seem apt.
How should I debug this? What is different about a command-line MSBuild from the in-IDE build? Hopefully somebody has had a similar experience and can let me know what was causal for them, so that I can give something a try.
Update 1:
It transpired that although I was targeting .NET Framework 4.6, some .csproj references copied over from the migrated project had entries for net472, despite NuGet packages themselves being selected for compatibility with .NET Framework 4.6.
I had to manually edit a few .csproj files. There were some reference issues in associated projects that then needed fixing.
The residual issue now is as follows:
The in-IDE build fails with a single error...
A PackageReference to Microsoft.Build.* without ExcludeAssets="runtime" exists in your project. This will cause MSBuild assemblies to be copied to your output directory, causing your application to load them at runtime. To use the copy of MSBuild registered by MSBuildLocator, set ExcludeAssets="runtime" on the MSBuild PackageReferences. To disable this check, set the property DisableMSBuildAssemblyCopyCheck=true in your project file (not recommended as you must distributed all of MSBuild + associated toolset). Package(s) referenced: Microsoft.Build.Framework
So I grepped my source code folder for <PackageReference Include="Microsoft.Build and only a single project was in the result list. When I checked this project file, the entry in question did have ExcludeAssets="runtime" so I am unsure why the error is reported. I have tried project cleans followed by rebuild, or deleting bin and obj folders before building, to no avail.
I guess my question now is whether <Package Include="Microsoft.Build are relevant, since these are not <ReferencePackage Include elements as mentioned in the error message.
Update 2:
I hang my head in shame. PBKAC regarding Update 1 error. I had sent a copy of the code to a build engineer who committed it to a branch in our VCS. I then cloned this branch to a different location, and copy+pasted my more recent changes over the top. However, the grep tool (AstroGrep) I was using was still pointing at the older location not in the VCS. The older location contained package references with ExcludeAssets="runtime" as required. However, the newer location did not. Once I noticed this, I corrected it by editing the faulty .csproj file and the error from Update 1 went away.
However, I still appear to have the original issue the question is about.
I am awaiting my company's security team to approve the use of MSBuildLog so that I can get more detail and hopefully find the cause.
One other commenter suggest moving to solution PackageReference build rather than using packages.config. There is a question as to why this is needed. I am aware this seems like it could create a significant amount of extra work due to: this for which there are workarounds, but the commenter mentioned a "need" to use NuGet this way, when I think it is optional. I wish to understand more before committing to such a change.
Unfortunately, this is one of those things where it's a case of user beware.
When using NuGet, it is possible for it to appear to have succeeded in updating a NuGet reference, but unless one checks the underlying packages.config meticulously, you may not be getting what you think.
As I am migrating a solution that used packages.config instead of <Project Reference .../> elements in .csproj files, I have been caught out by IDE default behaviour changes.
NuGet seems to update the .csproj using <PacakageReference.../> elements by default. But this does not amend the packages.config entries that may already exist. As such, I ended up with a mish-mash that MSBuild seemed confused about at build time. Rather than throw an error, it just did not build what was expected.
The old packages.config files had entries targeting .NET Framework of net472 in some cases. I was adding NuGet references to earlier versions for net46 since this is what I need to target now, and this resulted in the problem behaviour, since any unchanged net472 entries were no good for producing the build output.
Since the project needs to support VS2015 also, I need to rely on packages.config approach and not <PackageReference.../> approach, which was not updating older references in the expected way.
As such, I had to remove the NuGet <PacakgeReference.../> and re-introduce correct package versions in packages.config. Once these were all correct, the VSIX built OK.

Version number of NuGet pacakge specified in .csproj doesn't match version number of package

I've generated a new NuGet package and when I add it to a project the reference is wrong. This is kind of hard to describe but I'll do my best. The last version of this package was 3.3.11.0. I modified the code of the package, changed the assemblyinfo.cs to 3.64.1:
Changed the version in the .nuspec file:
Recompiled and ran NuGet pack to create the package and NuGet init to place it on our share and yet when I add the package to my project and the "Include" version is wrong:
What the heck is going on? I've been working with creating NuGet Packages for years and I've never seen anything like this.
The version of the actual generated .dll is correct as well:
UPDATE 1 2/7/20
Based on feedback I tried updating the major version number, but for some reason the version in the "Reference Include" section is always one behind the actual version number:
I believe this has to do with the Version Number you are setting it to.
Changing the minor number is not a breaking change and backwards compatible to the previous one.
What happens if you change the major number so NuGet knows it is a breaking change version. Might update the version number then as that version, 3.3.11.0 is no longer backwards compatible. Also what happens if you uninstall and reinstall instead of upgrading?

The feature 'nullable reference types' is currently in preview and *unsupported*

I want to add into my C# 8.0 projects Nullable#1.1.1 package but I don't want to enable it yet. Just add.
I'm using Visual Studio 2019 v16.3.10 and I installed it on each project by Manage NuGet Packages for Solution... option.
During rebuild of my solution I'm getting the error:
The feature 'nullable reference types' is currently in Preview and
unsupported. To use Preview features, use the 'preview' language version.
This error is exists for only 6 from 49 projects in my solution.
I removed from all of projects the LangVersion tag in favor one LangVersion tag into Directory.Build.props, so my Directory.Build.props looks like:
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
</Project>
I decided to don't add a Nullable tag with disable value to this file because it is the default value of Nullable package so it was not make a sense.
How can I solve that?
I have to ask because all of tips about Nullable are about how to enable it and didn't reply me for my error.
Edit:
I had to add Nullable#1.1.1 by NuGet Package because my projects are on .NET Framework 4.8.:
Nullability Attributes in Older Projects
In order to actually use
these attributes, they need to be defined. If you are using .NET
Standard 2.1 or .NET Core 3.0, that’s already done for you. Otherwise
you’ll have to create them as part of your project.
The traditional way of handling this would be to create a new .NET
Core 3 project, the use F12 to reverse engineer the desired
attributes. Then you can paste it into your project and add any
missing details, which for attributes only takes a few minutes.
An easier way is to simply install the Nullable package by Manuel
Römer. This will copy the NullableAttributes.cs file into your
project, which includes all of the necessary attributes. This package
has no compiled component, it is just the one source code file.
Either way, ensure all of the attributes are marked as "internal", not
public. This is to avoid collisions with other libraries that may also
be back-porting the attributes.
Using C# 8 and Nullable Reference Types in .NET Framework

How do I autoincrement the Package Version revision number when using a .Net Core format project file in VS2019

Previous answers to this question refer to editing the AssembyInfo.cs file to set the Assembly Version. I am generating a NuGet package using the new leaner .Net Core format of .csproj file for .Net Framework 4.6.1, and there is no AssemblyInfo.cs (or it's auto-generated and deleted).
If I try to set the Package Version property to 1.0.2.* in the project properties in VS2019, I get a popup error:
If possible, how can I get the revision number to auto-increment, ideally so on each build the number is incremented (1.0.2.45 => 1.0.2.46) and the number is retained across releases (1.0.2.46 => 1.0.3.47, manually editing the build/release number).
Note: I've already looked at the answer here, here and here and they all refer to the AssemblyVersion attribute. I want to update the Package Version (which is simply the Version in the CSProj file).
Update: One of the answers suggested a couple of GIT versions tools. I forgot to mention that TFS is used for a lot of the projects I want to use this on; these are work projects shared with other team members and are well established so could not easily be migrated to GIT without a lot of discussion even if it didn't get a simple veto by management as an unnecessary change.
First, on wildcards in assembly and package versions:
The wildcard for assembly (not package) versions is discouraged from being used - the new default for "sdk-style" projects use a compiler feature called "deterministic build" which aims to produce a binary identical output for every time the same unchanged source code is compiled. This mode does not allow for wildcards in assembly versions, which would change every 2 seconds.
However, this feature can be turned off by setting
<PropertyGroup>
<Deterministic>False</Deterministic>
</PropertyGroup>
If you then use a wildcard in your assembly version, the compiler will update your version based on the current time.
To re-use this assembly version for the package version, you need to add some additional build logic to your project file as described here: MSBuild /t:pack Nuget-Package has always the same Version
What I encourage to do:
A lot of projects use their git history for versioning, incrementing the version based on the git commit count.
I suggest looking into tools like Nerdbank.GitVersioning (lightweight and easy to use) or GitVersion (more features and better documentation) that allow you to configure how your versions can be automatically derived from the branches/tags that are being built.
There's no auto increment support for versioning nuget packages. You need to figure out/set the version number manually (or programmatically) through something like msbuild, a continuous integration platform, or third party tool.

C# project, compiler complaining missing reference to log4net

I am using Visual Studio 2017 to build a big C# project (200+ projects in the solution). When compiling one of the projects, I got many errors as shown below:
error CS0012: The type 'BufferingAppenderSkeleton' is defined in an assembly that is not referenced. You must add a reference to assembly 'log4net, Version=1.2.11.0, Culture=neutral, PublicKeyToken=1b44e1d426115821'.
The project in question, however, does reference to log4net 1.2.11. The only thing suspicious is the net40-full found in the package path of log4net: "C:\XXXX\Src\packages\log4net.1.2.11\lib\net40-full\log4net.dll"
in the package.config of the project, it contains this line:
<package id="log4net" version="1.2.11" targetFramework="net461" />
and in its app.config, it contains this line:
<dependentAssembly>
<assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.2.11.0" newVersion="1.2.11.0"/>
</dependentAssembly>
I wonder if it's the mismatch of the .net version (4.0 vs. 4.61) that causes the compiling error?
C# is not my primary area of expertise, but my understanding is that nuget looks into those config files to download needed packages, in this case, log4net. Then how come did it download the 4.0 version rather than that of 4.6.1?
my understanding is that nuget looks into those config files to download needed packages, in this case, log4net.
NuGet's job is just to download packages and extract whatever's in them, at least in the restore scenario of a package.config project. The targetFramework attribute in the packages.config file is only written, never read by the nuget client. I have no idea what it's purpose or intention was. Anyway, I believe the value of targetFramework is just the .NET Framework your project was using when the package was installed.
Then how come did it download the 4.0 version rather than that of 4.6.1?
Background information, skip to the next paragraph if you really don't care. If you go to the package page on nuget.org, you'll see in the version history that 1.2.11 isn't shown. However, if you look at the URLs for other versions, you can guess the URL for version 1.2.11. Quick off-topic comment, Fabio M was close, but not quite correct in saying the package doesn't exist any more. "nuget.org does not support permanent deletion of packages. Doing so would break every project depending on the availability of the package, especially with build workflows that involve package restore.". On the package version page, there's a message saying "The owner has unlisted this package. This could mean that the package is deprecated or shouldn't be used anymore".
Back to my point, once you're at this URL, change the n to an f in nuget.org to see the package version on fuget.org. Next to frameworks you can see a list of frameworks the package supports. net40 is the highest version that the package supports.
So, the reason why NuGet "downloaded the 4.0 version" is because that's the closest version that the nuget package provides that is compatible with your project. .NET is generally considered to be forward compatible, so net45 binaries work on the net462 runtime, so it's generally ok to use net45 binaries when your project is using a newer version.
Finally, about the error you're getting, as I said in my first paragraph, in packages.config projects, nuget's job is just to download and extract the package. At install time it adds some information to the csproj so the compiler can try to find the dll. So, if you look at your csproj, you should find a reference to log4net.dll, and it will contain a hint path that the compiler uses. If that hint path is wrong, then you'll get the errors you see. This is most common when projects are moved in the directory structure, but don't re-install the package. For example if the repo structure was origignally "project\project.csproj" and it's changed to "src\project\project.csproj", then the hint path of "..\packages\log4net.1.2.11\lib\net45\log4net.dll" is wrong, because an additional "..\" needs to be added so the relative path to the packages folder is correct. There may be other reasons the hint path is wrong, but this is the most common reason.

Categories