Skip to content

Grpc.Net.* 2.80.0 DLLs ship with FileVersion 2.66.0.0 — regression from 2.76.0.0 #2739

Description

@virzak

Summary

The DLLs in the 2.80.0 packages (Grpc.Net.Client, Grpc.Net.ClientFactory, Grpc.Net.Common, Grpc.Core.Api) all ship with FileVersion = 2.66.0.0, which is lower than the same DLLs in 2.76.0 (FileVersion = 2.76.0.0). ProductVersion is correct in both releases — only the Win32 FileVersion resource regressed.

2.80.0-pre1 is affected the same way; 2.76.0 is fine.

Reproduction

Any platform with PowerShell can reproduce by inspecting the DLL inside the NuGet packages:

$tmp = New-Item -ItemType Directory -Force -Path "$env:TEMP\grpc-check"
foreach ($pkg in 'grpc.net.client','grpc.net.clientfactory','grpc.net.common','grpc.core.api') {
  foreach ($v in '2.76.0','2.80.0') {
    $nupkg = Join-Path $tmp "$pkg-$v.nupkg"
    Invoke-WebRequest "https://api.nuget.org/v3-flatcontainer/$pkg/$v/$pkg.$v.nupkg" -OutFile $nupkg
    $zip = [System.IO.Compression.ZipFile]::OpenRead($nupkg)
    $entry = $zip.Entries | Where-Object { $_.FullName -match 'lib/net(8\.0|standard2\.[01])/[^/]+\.dll$' } | Select-Object -First 1
    $dll = Join-Path $tmp "$pkg-$v.dll"
    [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $dll, $true)
    $zip.Dispose()
    $info = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($dll)
    '{0,-25} {1,-7} -> FileVersion={2,-10} ProductVersion={3}' -f $pkg, $v, $info.FileVersion, $info.ProductVersion
  }
}

Output:

grpc.core.api             2.76.0  -> FileVersion=2.76.0.0  ProductVersion=2.76.0+c52862d2…
grpc.core.api             2.80.0  -> FileVersion=2.66.0.0  ProductVersion=2.80.0+f22747c7…
grpc.net.client           2.76.0  -> FileVersion=2.76.0.0  ProductVersion=2.76.0+c52862d2…
grpc.net.client           2.80.0  -> FileVersion=2.66.0.0  ProductVersion=2.80.0+f22747c7…
grpc.net.clientfactory    2.76.0  -> FileVersion=2.76.0.0  ProductVersion=2.76.0+c52862d2…
grpc.net.clientfactory    2.80.0  -> FileVersion=2.66.0.0  ProductVersion=2.80.0+f22747c7…
grpc.net.common           2.76.0  -> FileVersion=2.76.0.0  ProductVersion=2.76.0+c52862d2…
grpc.net.common           2.80.0  -> FileVersion=2.66.0.0  ProductVersion=2.80.0+f22747c7…

All four 2.80.0 DLLs share the suffix f22747c7…, suggesting they came from a single CI run. The uniform 2.66.0.0 looks like a stale build variable that wasn't bumped along with the package version.

Real-world impact

This breaks Windows Installer (MSI) major upgrades for any product that ships these DLLs. MSI uses Win32 FileVersion (not ProductVersion) to decide whether to overwrite an existing file. When a customer is upgrading an installation that has the 2.76.0 DLLs on disk:

  • File on disk: FileVersion = 2.76.0.0
  • Incoming MSI's payload: FileVersion = 2.66.0.0

MSI logs "Disallowing installation of component … since the same component with higher versioned keyfile exists" during CostFinalize, skips installing the four DLLs, and then RemoveExistingProducts deletes the on-disk copies as part of removing the old product. End state: the four DLLs are missing post-upgrade, the application fails to start, and uninstall + reinstall is the only customer-side workaround.

Workaround

Pin to Grpc.Net.Client / Grpc.Net.ClientFactory / Grpc.Net.Common / Grpc.Core.Api 2.76.0. Hold off on 2.80.x until a release with FileVersion >= 2.76.0.0 is published.

Suggested fix

In the CI/build pipeline that produces these packages, ensure the FileVersion MSBuild property (or equivalent AssemblyFileVersion attribute) is derived from the same source as the NuGet package version, so a release tag bump propagates to the Win32 resource as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions