Skip to content

Comments

Get accurate Windows version info from registry instead of os.release()#295842

Merged
dmitrivMS merged 22 commits intomainfrom
dev/dmitriv/fix-windows-version
Feb 23, 2026
Merged

Get accurate Windows version info from registry instead of os.release()#295842
dmitrivMS merged 22 commits intomainfrom
dev/dmitriv/fix-windows-version

Conversation

@dmitrivMS
Copy link
Contributor

@dmitrivMS dmitrivMS commented Feb 17, 2026

Fixes #197444

Changes
Used Windows registry to retrieve Windows release and build numbers.
Added passing User-Agent header to update service.
Updated installer launch env to ignore compat mode.

Note
When running in compatibility mode os.release() may return incorrect version info which leads to VS Code downgrade (downloading an old version) and terminal not working.

Validation
Start VS Code with compatibility settings 8.1, wait for update to be installed -> verify the update is next version (not an old one), click Restart -> VS Code should restart into the new version. You should see no errors anywhere along the way. Verify terminal works under these conditions.

@dmitrivMS dmitrivMS added this to the February 2026 milestone Feb 17, 2026
@dmitrivMS dmitrivMS requested a review from Tyriar February 17, 2026 20:12
@dmitrivMS dmitrivMS self-assigned this Feb 17, 2026
@dmitrivMS dmitrivMS added install-update VS Code installation and upgrade system issues terminal General terminal issues that don't fall under another label labels Feb 17, 2026
Copilot AI review requested due to automatic review settings February 17, 2026 20:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Windows version detection when running VS Code in compatibility mode by reading accurate version information from the Windows registry instead of relying on os.release(), which can return incorrect values due to the deprecated GetVersionEx API.

Changes:

  • Created a new windowsVersion.ts module that reads Windows version info from the registry using @vscode/windows-registry
  • Replaced all usages of the old getWindowsBuildNumber() function with new async/sync variants
  • Added initialization of Windows version info during app startup to ensure accurate data is available

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/vs/base/node/windowsVersion.ts New module providing registry-based Windows version detection with async/sync APIs
src/vs/code/electron-main/main.ts Added initialization call for Windows version info during app startup
src/vs/platform/windows/electron-main/windowsMainService.ts Updated to use async getWindowsRelease() for window configuration
src/vs/platform/terminal/node/terminalEnvironment.ts Removed old getWindowsBuildNumber() function, updated to use async version
src/vs/platform/terminal/node/terminalProfiles.ts Updated to use async getWindowsBuildNumberAsync()
src/vs/platform/terminal/node/terminalProcess.ts Updated to use sync getWindowsBuildNumberSync() in constructor
src/vs/platform/terminal/node/ptyService.ts Updated to use async getWindowsBuildNumberAsync() in async methods
src/vs/platform/remote/node/wsl.ts Removed duplicate getWindowsBuildNumber() function, updated to use async version
src/vs/platform/terminal/test/node/terminalEnvironment.test.ts Updated test conditions to use async getWindowsBuildNumberAsync()
Comments suppressed due to low confidence (1)

src/vs/platform/terminal/test/node/terminalEnvironment.test.ts:43

  • This top-level await in the conditional suite selection won't work correctly. The suite function is called synchronously during test discovery, but the await expression makes this asynchronous. This means the condition will always evaluate using the Promise object itself (which is truthy), not the awaited value.

Consider using getWindowsBuildNumberSync() instead, or restructure the test to evaluate the condition inside a setup function and use suite.skip() conditionally.

		(await getWindowsBuildNumberAsync() < 18309 ? suite.skip : suite)('pwsh', async () => {

@dmitrivMS dmitrivMS requested a review from joaomoreno February 19, 2026 00:40
@dmitrivMS dmitrivMS added the windows VS Code on Windows issues label Feb 19, 2026
@dmitrivMS dmitrivMS marked this pull request as ready for review February 20, 2026 00:50
@vs-code-engineering
Copy link

vs-code-engineering bot commented Feb 20, 2026

📬 CODENOTIFY

The following users are being notified based on files changed in this PR:

@bpasero

Matched files:

  • src/vs/code/electron-main/main.ts
  • src/vs/platform/windows/electron-main/windowsMainService.ts

@deepak1556

Matched files:

  • src/vs/code/electron-main/main.ts

@dmitrivMS dmitrivMS requested a review from deepak1556 February 20, 2026 00:51
@dmitrivMS dmitrivMS enabled auto-merge (squash) February 20, 2026 00:59
Copy link
Member

@bpasero bpasero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am worried about the impact on startup performance such a change has. We now block window opening with this new code that asks the windows registry for something which we do not know when it returns. If we need this info in a reliable way, then it should be moved to the places where we need it and wait there but with sensitive fallback mechanisms if the windows registry is very slow.

@dmitrivMS
Copy link
Contributor Author

I am worried about the impact on startup performance such a change has. We now block window opening with this new code that asks the windows registry for something which we do not know when it returns. If we need this info in a reliable way, then it should be moved to the places where we need it and wait there but with sensitive fallback mechanisms if the windows registry is very slow.

Fixed - using sync version. This value is only ever used to check OS release on Mac, and the new functionality is not useful there - so even if by any chance it is not initialized by the time this runs, it should be fine.

@dmitrivMS dmitrivMS requested a review from bpasero February 20, 2026 21:21
Copy link
Collaborator

@deepak1556 deepak1556 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM on the usage in update code, also like that the registry information is cached for the lifetime of the process.

No blockers from my end, what would be nice is we only get the information from registry if we are running in compatibility mode but again checking if we are in compat mode requires probing registry :(

@dmitrivMS
Copy link
Contributor Author

LGTM on the usage in update code, also like that the registry information is cached for the lifetime of the process.

No blockers from my end, what would be nice is we only get the information from registry if we are running in compatibility mode but again checking if we are in compat mode requires probing registry :(

I think there may be env variable to check for compat mode, but I'd rather not rely on that - I actually like the fact that it's consistent always getting OS info from the source.

@deepak1556
Copy link
Collaborator

The trade off I was coming at is, os.release gets the version information from RtlGetVersion kernel api https://github.com/libuv/libuv/blob/edfc95dbd707becd2e49cda69184030be2f46164/src/win/util.c#L1568-L1726 which should be faster than reading from registry.

From https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversion

Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersion will always return the version that the application is manifested for in future releases.

From https://learn.microsoft.com/en-us/windows/win32/sysinfo/targeting-your-application-at-windows-8-1

In Windows 8.1 and later, the GetVersion and GetVersionEx functions have been deprecated. As of Windows 10, the VerifyVersionInfo function is also deprecated. You can still call the deprecated functions, but if your application doesn't specifically target Windows 8.1 or later, then the functions will return the Windows 8 version (6.2).

We do ship a manifest today https://github.com/microsoft/vscode/blob/main/resources/win32/appx/AppxManifest.xml without any compatibility section https://learn.microsoft.com/en-us/windows/win32/sysinfo/targeting-your-application-at-windows-8-1, but again the manifest is not properly assigned to the executable because of a known bug in the OS #254613 (comment), could this be the cause rather than being invoked as compat mode for the bug ?

Followup would be,

  1. The fix for the sandbox crash is currently being shipped in the OS (don't know the exact state of the rollout, it was mentioned 24H2 Germanium and newer)
  2. Re-enable the manifest with supportedOS section for windows 10 and 11, our runtime does not support windows 8 in anyway
  3. If os.release still returns 6.2 then only fallback to reading from registry ?

@dmitrivMS dmitrivMS dismissed bpasero’s stale review February 22, 2026 00:45

Switched to sync version to avoid delays.

Copy link
Member

@bpasero bpasero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is better but its fragile: we do not have a deterministic release info on the window anymore now because initWindowsVersionInfo may or may not succeed at the time the window opens. I think a better approach is to leave os.release() in for the window and use the async variant in places were we really need to rely on it and where we can wait on it without causing issues.

@dmitrivMS
Copy link
Contributor Author

I think this is better but its fragile: we do not have a deterministic release info on the window anymore now because initWindowsVersionInfo may or may not succeed at the time the window opens. I think a better approach is to leave os.release() in for the window and use the async variant in places were we really need to rely on it and where we can wait on it without causing issues.

Sure, no problem - reverted the change. This property is not used for anything of significance on Windows, so it should be fine. Ideally, we should remove it - since it cannot be properly initialized, it may return incorrect value on Windows.

@dmitrivMS dmitrivMS dismissed bpasero’s stale review February 23, 2026 11:51

Reverted disputed change.

@dmitrivMS
Copy link
Contributor Author

@deepak1556 We read once and cache it, I don't see it as a perf concern to be honest.
Regarding upstream fixes - it feels like too much to depend on, and getting the value from the registry should give us a reliable solution now and going forward.

@deepak1556
Copy link
Collaborator

I am also not concerned about performance in this implementation however when the registry read fails and os.release returns 6.2 what is the option to get the correct version information (hence I was hinting at fixing os.release eventually so get maximum coverage). Should we get some signal in the update service as part this PR to understand the number of affected users that will be in this category ?

@dmitrivMS dmitrivMS merged commit 4eb8565 into main Feb 23, 2026
19 checks passed
@dmitrivMS dmitrivMS deleted the dev/dmitriv/fix-windows-version branch February 23, 2026 15:06
@dmitrivMS
Copy link
Contributor Author

I am also not concerned about performance in this implementation however when the registry read fails and os.release returns 6.2 what is the option to get the correct version information (hence I was hinting at fixing os.release eventually so get maximum coverage). Should we get some signal in the update service as part this PR to understand the number of affected users that will be in this category ?

I'll see if I can detect and log running in compat mode!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

install-update VS Code installation and upgrade system issues terminal General terminal issues that don't fall under another label windows VS Code on Windows issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

VS code 1.84 automatically installs 1.79 (Old)

4 participants