From ed8116ac09f27ce5fa834dd3ee7a185047b00388 Mon Sep 17 00:00:00 2001 From: Nikola Metulev <711864+nmetulev@users.noreply.github.com> Date: Fri, 17 Jul 2026 18:43:20 -0700 Subject: [PATCH 1/3] Resolve Windows metadata from .NET SDK ref pack on SDK-less hosts The shipped MSBuild targets default `CsWinRTWindowsMetadata` to a bare Windows SDK version (`$(WindowsSDKVersion)`/`$(TargetPlatformVersion)`), which `cswinrt.exe` can only resolve via the registry (`HKLM\...\Windows Kits\Installed Roots\KitsRoot10`). On hosts with no registered Windows SDK (clean CI agents, containers, SDK-less dev machines) that lookup throws "Could not find the Windows SDK in the registry", cascading into downstream (e.g. XAML) build failures. Add `CsWinRTResolveWindowsMetadataFromSdkRefPack`, which - only when no Windows SDK is registered and the value is still the bare-version default - repoints `CsWinRTWindowsMetadata` at the `\winmd` folder of the `Microsoft.Windows.SDK.NET.Ref` projection ref pack the .NET SDK already restores for `net*-windows10.0.x` TFMs (resolved robustly via `@(ResolvedTargetingPack)`, versioned to `$(TargetPlatformVersion)`). Registered -SDK builds (Visual Studio, SDK-installed CI) and explicit `CsWinRTWindowsMetadata` values are unaffected. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f8b6648-c42b-4fca-98a7-2025142b37bd --- nuget/Microsoft.Windows.CsWinRT.targets | 60 +++++++++++++++++++++++++ nuget/readme.md | 10 +++++ 2 files changed, 70 insertions(+) diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets index 9c144cf6df..78d23b2bb5 100644 --- a/nuget/Microsoft.Windows.CsWinRT.targets +++ b/nuget/Microsoft.Windows.CsWinRT.targets @@ -79,6 +79,66 @@ Copyright (C) Microsoft Corporation. All rights reserved. + + + + + + <_CsWinRTKitsRoot10>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot10', null, Microsoft.Win32.RegistryView.Registry32, Microsoft.Win32.RegistryView.Registry64)) + + + <_CsWinRTWindowsMetadataIsBareVersion Condition="'$(CsWinRTWindowsMetadata)' != '' and + '$(CsWinRTWindowsMetadata)' != 'local' and + '$(CsWinRTWindowsMetadata)' != 'sdk' and + '$(CsWinRTWindowsMetadata)' != 'sdk+' and + !Exists('$(CsWinRTWindowsMetadata)')">true + + + + + <_CsWinRTSdkNetRefPackDir Include="@(ResolvedTargetingPack->'%(Path)')" + Condition="'%(ResolvedTargetingPack.NuGetPackageId)' == 'Microsoft.Windows.SDK.NET.Ref'" /> + <_CsWinRTSdkNetRefPackDirDistinct Include="@(_CsWinRTSdkNetRefPackDir->Distinct())" /> + + + + <_CsWinRTSdkNetRefPackWinMDDir Condition="'@(_CsWinRTSdkNetRefPackDirDistinct)' != ''">@(_CsWinRTSdkNetRefPackDirDistinct)\winmd + $(_CsWinRTSdkNetRefPackWinMDDir) + + + + + diff --git a/nuget/readme.md b/nuget/readme.md index cc027eca67..08f1459204 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -90,6 +90,16 @@ Windows Metadata is required for all C#/WinRT projections, and can be supplied b If a Windows SDK is installed, $(WindowsSDKVersion) is defined when building from a VS command prompt. +If no Windows SDK is registered on the machine (for example on clean CI agents, containers, or SDK-less +developer machines), the default `$(WindowsSDKVersion)`/`$(TargetPlatformVersion)` value is a bare SDK +version number that `cswinrt.exe` can only resolve through the registry, so the build would otherwise fail +with "Could not find the Windows SDK in the registry". In that case, for modern .NET TFMs (e.g. +`net*-windows10.0.x`), C#/WinRT automatically falls back to the Windows metadata (`.winmd`) files shipped in +the `Microsoft.Windows.SDK.NET.Ref` projection ref pack that the .NET SDK restores (its `\winmd` folder, +versioned to `$(TargetPlatformVersion)`). This fallback only applies when no Windows SDK is registered and +`$(CsWinRTWindowsMetadata)` is still the bare-version default; an explicit `$(CsWinRTWindowsMetadata)` value +(a path, or `local`/`sdk`) and registered-SDK builds are unaffected. + ## Consuming and Producing The C#/WinRT package can be used both to consume WinRT types, and to produce them (via CsWinRTComponent). It is also possible to combine these settings and do both. For example, a developer might want to *produce* a library that's implemented in terms of another WinRT runtime class (*consuming* it). From 7271a49facf9f8dfd2cae83f0099747e063b2466 Mon Sep 17 00:00:00 2001 From: Nikola Metulev <711864+nmetulev@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:15:28 -0700 Subject: [PATCH 2/3] Clarify ref-pack resolution tolerates preview/suffix versions Document (in the targets comment) that @(ResolvedTargetingPack) resolves the actually-restored Microsoft.Windows.SDK.NET.Ref pack via the SDK's own targeting-pack resolution, so it tolerates ref-pack versions that do not string-match $(TargetPlatformVersion) (e.g. a 10.0.26100.67-preview pack for a project targeting 10.0.26100.0) - which an exact-version lookup would miss. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f8b6648-c42b-4fca-98a7-2025142b37bd --- nuget/Microsoft.Windows.CsWinRT.targets | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets index 78d23b2bb5..adcaa1b799 100644 --- a/nuget/Microsoft.Windows.CsWinRT.targets +++ b/nuget/Microsoft.Windows.CsWinRT.targets @@ -123,7 +123,14 @@ Copyright (C) Microsoft Corporation. All rights reserved. - + <_CsWinRTSdkNetRefPackDir Include="@(ResolvedTargetingPack->'%(Path)')" Condition="'%(ResolvedTargetingPack.NuGetPackageId)' == 'Microsoft.Windows.SDK.NET.Ref'" /> <_CsWinRTSdkNetRefPackDirDistinct Include="@(_CsWinRTSdkNetRefPackDir->Distinct())" /> From cc67f3aae7fea095cc8a8f21e6ca5bf78c1bf41f Mon Sep 17 00:00:00 2001 From: Nikola Metulev Date: Fri, 17 Jul 2026 21:24:14 -0700 Subject: [PATCH 3/3] Update nuget/Microsoft.Windows.CsWinRT.targets Co-authored-by: Manodasan Wignarajah --- nuget/Microsoft.Windows.CsWinRT.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets index adcaa1b799..be41c5620d 100644 --- a/nuget/Microsoft.Windows.CsWinRT.targets +++ b/nuget/Microsoft.Windows.CsWinRT.targets @@ -143,7 +143,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. + Text="C#/WinRT: no Windows SDK is registered; using Windows metadata from the Windows SDK projection ref pack: '$(_CsWinRTSdkNetRefPackWinMDDir)'." />