diff --git a/.github/scripts/assert-server2012-installer-smoke.ps1 b/.github/scripts/assert-server2012-installer-smoke.ps1 new file mode 100644 index 0000000000..a7518390eb --- /dev/null +++ b/.github/scripts/assert-server2012-installer-smoke.ps1 @@ -0,0 +1,75 @@ +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$InstallerPath, + [int]$StartupSeconds = 20 +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +$os = [System.Environment]::OSVersion.Version +if ($os.Major -ne 6 -or ($os.Minor -ne 1 -and $os.Minor -ne 3)) { + throw "The installer smoke test requires Windows 7 or Server 2012 R2 (kernel 6.1/6.3), detected $($os.ToString())." +} + +$installerPath = (Resolve-Path -LiteralPath $InstallerPath).Path +$testRoot = Join-Path ([System.IO.Path]::GetTempPath()) "dbx-server2012-installer-smoke" +$resolvedTemp = (Resolve-Path -LiteralPath ([System.IO.Path]::GetTempPath())).Path.TrimEnd('\') +$resolvedTestRoot = [System.IO.Path]::GetFullPath($testRoot).TrimEnd('\') +if (!$resolvedTestRoot.StartsWith("$resolvedTemp\", [System.StringComparison]::OrdinalIgnoreCase)) { + throw "Refusing to use a smoke-test directory outside the system temporary directory: $resolvedTestRoot" +} + +if (Test-Path -LiteralPath $resolvedTestRoot) { + Remove-Item -LiteralPath $resolvedTestRoot -Recurse -Force +} + +$appProcess = $null +try { + $installer = Start-Process -FilePath $installerPath -ArgumentList @("/S", "/D=$resolvedTestRoot") -Wait -PassThru + if ($installer.ExitCode -ne 0) { + throw "Server 2012 R2 test installer failed with exit code $($installer.ExitCode)." + } + + $appPath = Join-Path $resolvedTestRoot "dbx.exe" + $runtimePath = Join-Path $resolvedTestRoot "webview2-fixed-runtime\msedgewebview2.exe" + foreach ($requiredPath in @($appPath, $runtimePath)) { + if (!(Test-Path -LiteralPath $requiredPath -PathType Leaf)) { + throw "Server 2012 R2 installer omitted required file: $requiredPath" + } + } + + $env:WEBVIEW2_BROWSER_EXECUTABLE_FOLDER = Join-Path $resolvedTestRoot "webview2-fixed-runtime" + $env:WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS = "--no-sandbox --disable-gpu" + $env:DBX_STARTUP_LOG_DIR = Join-Path $resolvedTestRoot "smoke-logs" + New-Item -ItemType Directory -Path $env:DBX_STARTUP_LOG_DIR -Force | Out-Null + + $appProcess = Start-Process -FilePath $appPath -PassThru + Start-Sleep -Seconds $StartupSeconds + $appProcess.Refresh() + if ($appProcess.HasExited) { + $startupLog = Join-Path $env:DBX_STARTUP_LOG_DIR "startup.log" + $logText = if (Test-Path -LiteralPath $startupLog) { + Get-Content -LiteralPath $startupLog -Raw + } else { + "" + } + throw "DBX exited during the Server 2012 R2 startup smoke test with code $($appProcess.ExitCode).`n$logText" + } + + Write-Host "Server 2012 R2 installer smoke test passed after $StartupSeconds seconds: $installerPath" +} +finally { + if ($null -ne $appProcess -and !$appProcess.HasExited) { + Stop-Process -Id $appProcess.Id -Force -ErrorAction SilentlyContinue + } + + $uninstallerPath = Join-Path $resolvedTestRoot "uninstall.exe" + if (Test-Path -LiteralPath $uninstallerPath -PathType Leaf) { + $uninstaller = Start-Process -FilePath $uninstallerPath -ArgumentList @("/S", "_?=$resolvedTestRoot") -Wait -PassThru + if ($uninstaller.ExitCode -ne 0) { + Write-Warning "Server 2012 R2 test uninstaller returned exit code $($uninstaller.ExitCode)." + } + } +} diff --git a/.github/scripts/assert-webview2-server2012-runtime.ps1 b/.github/scripts/assert-webview2-server2012-runtime.ps1 new file mode 100644 index 0000000000..a0fa0db2fe --- /dev/null +++ b/.github/scripts/assert-webview2-server2012-runtime.ps1 @@ -0,0 +1,67 @@ +[CmdletBinding()] +param( + [string]$RuntimeDirectory = (Join-Path $PSScriptRoot "..\..\src-tauri\webview2-fixed-runtime"), + [string]$LoaderPath = (Join-Path ([System.IO.Path]::GetTempPath()) "dbx-win7-webview2-loader-probe\WebView2Loader.dll"), + [string]$ExpectedVersion = "109.0.1518.78" +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +$os = [System.Environment]::OSVersion.Version +if ($os.Major -ne 6 -or ($os.Minor -ne 1 -and $os.Minor -ne 3)) { + throw "The offline runtime probe requires Windows 7 or Server 2012 R2 (kernel 6.1/6.3), detected $($os.ToString())." +} + +$runtimeDirectory = (Resolve-Path -LiteralPath $RuntimeDirectory).Path +$loaderPath = (Resolve-Path -LiteralPath $LoaderPath).Path +$runtimeExecutable = Join-Path $runtimeDirectory "msedgewebview2.exe" +if (!(Test-Path -LiteralPath $runtimeExecutable -PathType Leaf)) { + throw "WebView2 fixed runtime executable does not exist: $runtimeExecutable" +} + +$escapedLoaderPath = $loaderPath.Replace('"', '""') +$source = @" +using System; +using System.Runtime.InteropServices; + +public static class DbxServer2012WebView2Probe +{ + [DllImport(@"$escapedLoaderPath", CharSet = CharSet.Unicode, ExactSpelling = true)] + public static extern int GetAvailableCoreWebView2BrowserVersionString( + string browserExecutableFolder, + out IntPtr versionInfo); +} +"@ + +Add-Type -TypeDefinition $source -Language CSharp +$versionPointer = [IntPtr]::Zero +$result = [DbxServer2012WebView2Probe]::GetAvailableCoreWebView2BrowserVersionString( + $runtimeDirectory, + [ref]$versionPointer +) + +$resultHex = [System.BitConverter]::ToUInt32( + [System.BitConverter]::GetBytes([int32]$result), + 0 +) +$hresult = "0x{0:X8}" -f $resultHex +if ($result -ne 0) { + throw "Server 2012 R2 WebView2 loader rejected the fixed runtime with HRESULT $hresult." +} +if ($versionPointer -eq [IntPtr]::Zero) { + throw "Server 2012 R2 WebView2 loader returned an empty version pointer." +} + +try { + $version = [Runtime.InteropServices.Marshal]::PtrToStringUni($versionPointer) +} +finally { + [Runtime.InteropServices.Marshal]::FreeCoTaskMem($versionPointer) +} + +if ([string]::IsNullOrWhiteSpace($version) -or !$version.StartsWith($ExpectedVersion)) { + throw "Expected WebView2 fixed runtime $ExpectedVersion, detected '$version'." +} + +Write-Host "Server 2012 R2 WebView2 runtime probe passed: loader=$loaderPath runtime=$runtimeDirectory version=$version" diff --git a/.github/scripts/invoke-server2012-remote-validation.ps1 b/.github/scripts/invoke-server2012-remote-validation.ps1 new file mode 100644 index 0000000000..833e3bee93 --- /dev/null +++ b/.github/scripts/invoke-server2012-remote-validation.ps1 @@ -0,0 +1,93 @@ +[CmdletBinding(DefaultParameterSetName = "Runtime")] +param( + [Parameter(Mandatory = $true)] + [string]$ComputerName, + [Parameter(Mandatory = $true)] + [string]$UserName, + [string]$Password = $env:SERVER2012_PASSWORD, + [Parameter(Mandatory = $true)] + [ValidateSet("Runtime", "Installer")] + [string]$Mode, + [Parameter(Mandatory = $true, ParameterSetName = "Runtime")] + [string]$RuntimeDirectory, + [Parameter(Mandatory = $true, ParameterSetName = "Runtime")] + [string]$LoaderPath, + [Parameter(Mandatory = $true, ParameterSetName = "Installer")] + [string]$InstallerPath, + [switch]$UseSsl +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +if ([string]::IsNullOrWhiteSpace($Password)) { + throw "SERVER2012_PASSWORD is required." +} + +$securePassword = ConvertTo-SecureString $Password -AsPlainText -Force +$credential = New-Object System.Management.Automation.PSCredential($UserName, $securePassword) +$sessionParameters = @{ + ComputerName = $ComputerName + Credential = $credential + Authentication = "Negotiate" + ErrorAction = "Stop" +} +$useSslEnabled = $UseSsl -or $env:SERVER2012_USE_SSL -eq "true" +if ($useSslEnabled) { + $sessionParameters.UseSSL = $true + $sessionParameters.SessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck +} + +$session = $null +$remoteRoot = "C:\Windows\Temp\dbx-server2012-ci-$([Guid]::NewGuid().ToString('N'))" +try { + $session = New-PSSession @sessionParameters + Invoke-Command -Session $session -ScriptBlock { + param($Path) + New-Item -ItemType Directory -Path $Path -Force | Out-Null + } -ArgumentList $remoteRoot + + if ($Mode -eq "Runtime") { + $runtimeDirectory = (Resolve-Path -LiteralPath $RuntimeDirectory).Path + $loaderPath = (Resolve-Path -LiteralPath $LoaderPath).Path + $probeScript = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "assert-webview2-server2012-runtime.ps1")).Path + + Copy-Item -LiteralPath $runtimeDirectory -Destination "$remoteRoot\webview2-fixed-runtime" -Recurse -ToSession $session + Copy-Item -LiteralPath $loaderPath -Destination "$remoteRoot\WebView2Loader.dll" -ToSession $session + Copy-Item -LiteralPath $probeScript -Destination "$remoteRoot\assert-runtime.ps1" -ToSession $session + + Invoke-Command -Session $session -ScriptBlock { + param($Root) + & "$Root\assert-runtime.ps1" ` + -RuntimeDirectory "$Root\webview2-fixed-runtime" ` + -LoaderPath "$Root\WebView2Loader.dll" + } -ArgumentList $remoteRoot + } else { + $installerPath = (Resolve-Path -LiteralPath $InstallerPath).Path + $smokeScript = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "assert-server2012-installer-smoke.ps1")).Path + + Copy-Item -LiteralPath $installerPath -Destination "$remoteRoot\installer.exe" -ToSession $session + Copy-Item -LiteralPath $smokeScript -Destination "$remoteRoot\assert-installer.ps1" -ToSession $session + + Invoke-Command -Session $session -ScriptBlock { + param($Root) + & "$Root\assert-installer.ps1" -InstallerPath "$Root\installer.exe" + } -ArgumentList $remoteRoot + } +} +finally { + if ($null -ne $session) { + Invoke-Command -Session $session -ScriptBlock { + param($Path) + $windowsTemp = [System.IO.Path]::GetFullPath("C:\Windows\Temp").TrimEnd('\') + $resolvedPath = [System.IO.Path]::GetFullPath($Path).TrimEnd('\') + if (!$resolvedPath.StartsWith("$windowsTemp\dbx-server2012-ci-", [System.StringComparison]::OrdinalIgnoreCase)) { + throw "Refusing to clean an unexpected remote validation directory: $resolvedPath" + } + if (Test-Path -LiteralPath $resolvedPath) { + Remove-Item -LiteralPath $resolvedPath -Recurse -Force + } + } -ArgumentList $remoteRoot + Remove-PSSession $session + } +} diff --git a/.github/scripts/prepare-webview2-win7-loader.ps1 b/.github/scripts/prepare-webview2-win7-loader.ps1 index 723fe1f64a..4c7df3cefb 100644 --- a/.github/scripts/prepare-webview2-win7-loader.ps1 +++ b/.github/scripts/prepare-webview2-win7-loader.ps1 @@ -4,11 +4,16 @@ param() Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" -# Newer WebView2 static loaders import EventSetInformation, which does not exist on Windows 7. -# The loader entry points are stable, so the Win7 bundle uses the last verified compatible SDK loader. -$sdkVersion = "1.0.1054.31" -$sdkPackageSha256 = "0afe683aa3d143a5f6330db1ce833c69278b38fe5e1eadec52f26910ad26e22f" -$loaderSha256 = "76314119685bbf4c2b2423a44e81b57beadc914c943d0e772fd6bc78c8e6b0e8" +# WebView2 static loaders newer than SDK 1.0.1054 import EventSetInformation, which does +# not exist on Windows 7, while 1.0.1054.31 itself fails on Server 2012 R2 with +# ERROR_NOT_SUPPORTED (0x80070032, MicrosoftEdge/WebView2Feedback#2025). SDK 1.0.902.49 is +# the loader verified on both Windows 7 SP1 and Server 2012 R2 real machines, so the single +# win7 + server 2012 r2 offline bundle links it instead of the webview2-com-sys default. +$sdkVersion = "1.0.902.49" +$sdkPackageSha256 = "b483c906b03690267108f4304d456eac0e718131ef994e69aaa5a21532b512c6" +$loaderSha256 = "aa5c26670f1b18d0fa2a56ac3f1ae30110c332a8bfbd555a7be3e548d1b0da3d" +$loaderDllSha256 = "fdf978ba706578b05967d7f0181f462147864a5aa74f36016a62cb3d3dbe6909" +$legacy1054LoaderSha256 = "76314119685bbf4c2b2423a44e81b57beadc914c943d0e772fd6bc78c8e6b0e8" $webView2ComSysVersion = "0.38.2" $upstreamLoaderSha256 = "0659b741bde6348d4c4a6ec4ceb9af50e3d0048ed9cd3c8659bccbb61fde55ee" @@ -19,9 +24,10 @@ $extractedPath = Join-Path $temporaryRoot "extracted" try { New-Item -ItemType Directory -Path $extractedPath -Force | Out-Null + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $packageUrl = "https://www.nuget.org/api/v2/package/Microsoft.Web.WebView2/$sdkVersion" - Write-Host "Downloading WebView2 SDK $sdkVersion for the Windows 7 loader..." + Write-Host "Downloading WebView2 SDK $sdkVersion for the Windows 7 / Server 2012 R2 loader..." Invoke-WebRequest -Uri $packageUrl -OutFile $packagePath -UseBasicParsing $actualPackageSha256 = (Get-FileHash -LiteralPath $packagePath -Algorithm SHA256).Hash.ToLowerInvariant() @@ -44,7 +50,12 @@ try { $actualLoaderSha256 = (Get-FileHash -LiteralPath $legacyLoader -Algorithm SHA256).Hash.ToLowerInvariant() if ($actualLoaderSha256 -ne $loaderSha256) { - throw "Unexpected Windows 7 WebView2 loader SHA256: $actualLoaderSha256" + throw "Unexpected Windows 7 / Server 2012 R2 WebView2 loader SHA256: $actualLoaderSha256" + } + + $actualLoaderDllSha256 = (Get-FileHash -LiteralPath $legacyLoaderDll -Algorithm SHA256).Hash.ToLowerInvariant() + if ($actualLoaderDllSha256 -ne $loaderDllSha256) { + throw "Unexpected Windows 7 / Server 2012 R2 WebView2 loader DLL SHA256: $actualLoaderDllSha256" } Push-Location $repositoryRoot @@ -78,7 +89,7 @@ try { } $existingLoaderSha256 = (Get-FileHash -LiteralPath $loaderDestination -Algorithm SHA256).Hash.ToLowerInvariant() - $knownLoaderHashes = @($upstreamLoaderSha256, $loaderSha256) + $knownLoaderHashes = @($upstreamLoaderSha256, $legacy1054LoaderSha256, $loaderSha256) if ($existingLoaderSha256 -notin $knownLoaderHashes) { throw "Refusing to replace an unknown webview2-com-sys loader SHA256: $existingLoaderSha256" } @@ -96,7 +107,7 @@ try { $probeLoader = Join-Path $probeDirectory "WebView2Loader.dll" Copy-Item -LiteralPath $legacyLoaderDll -Destination $probeLoader -Force - Write-Host "Prepared WebView2 SDK $sdkVersion static loader for Windows 7: $loaderDestination" + Write-Host "Prepared WebView2 SDK $sdkVersion static loader for Windows 7 / Server 2012 R2: $loaderDestination" Write-Host "Prepared WebView2 SDK $sdkVersion loader probe DLL: $probeLoader" } finally { diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2ce58c1a85..93bfe2a592 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -619,7 +619,7 @@ jobs: VSIGN_OPERATOR_PWD: ${{ secrets.VSIGN_OPERATOR_PWD }} run: ./.github/scripts/setup-vsign.ps1 - - name: Bundle and upload Windows 7 fixed-runtime installer + - name: Bundle and upload Windows 7 / Server 2012 R2 fixed-runtime installer shell: pwsh env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -628,7 +628,8 @@ jobs: run: | $version = "${env:GITHUB_REF_NAME}".TrimStart("v") $bundleDir = "target/x86_64-win7-windows-msvc/release/bundle/nsis" - $offlineName = "DBX_${version}_x64-win7-webview2-109-offline-setup.exe" + $offlineName = "DBX_${version}_x64-win7-server2012r2-webview2-109-offline-setup.exe" + $checksumName = "${offlineName}.sha256" $cargoMetadata = cargo metadata --no-deps --format-version 1 | ConvertFrom-Json $appVersion = ($cargoMetadata.packages | Where-Object { $_.name -eq "dbx" } | Select-Object -First 1).version @@ -645,7 +646,7 @@ jobs: Sort-Object LastWriteTimeUtc -Descending | Select-Object -First 1 if (!$installer) { - Write-Error "Missing Windows 7 fixed-runtime installer in ${bundleDir}" + Write-Error "Missing Windows 7 / Server 2012 R2 fixed-runtime installer in ${bundleDir}" exit 1 } @@ -653,7 +654,10 @@ jobs: ./.github/scripts/assert-authenticode.ps1 -Path $installer.FullName Copy-Item $installer.FullName $offlineName -Force - gh release upload "${env:GITHUB_REF_NAME}" $offlineName --repo "${env:GITHUB_REPOSITORY}" --clobber + $hash = (Get-FileHash -LiteralPath $offlineName -Algorithm SHA256).Hash.ToLowerInvariant() + "$hash $offlineName" | Set-Content -LiteralPath $checksumName -Encoding ascii + gh release upload "${env:GITHUB_REF_NAME}" $offlineName $checksumName ` + --repo "${env:GITHUB_REPOSITORY}" --clobber - name: Remove temporary VSign files if: always() diff --git a/.github/workflows/windows-server-2012-r2.yml b/.github/workflows/windows-server-2012-r2.yml new file mode 100644 index 0000000000..7dd753d9aa --- /dev/null +++ b/.github/workflows/windows-server-2012-r2.yml @@ -0,0 +1,143 @@ +name: Windows Server 2012 R2 Offline Compatibility + +on: + workflow_dispatch: + inputs: + run_remote_smoke_test: + description: Run the optional WinRM smoke test after building + required: true + default: false + type: boolean + +permissions: + contents: read + +concurrency: + group: windows-server-2012-r2-${{ github.ref }} + cancel-in-progress: true + +env: + CARGO_INCREMENTAL: "0" + RUSTFLAGS: -C debuginfo=line-tables-only -C target-feature=+crt-static + +jobs: + build-win7-server2012r2-offline: + name: Build Win7 / Server 2012 R2 Offline Installer + runs-on: windows-2022 + timeout-minutes: 90 + steps: + - uses: actions/checkout@v5 + + - name: Setup pnpm + uses: pnpm/action-setup@v6 + with: + version: 10.27.0 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: 22.13.0 + cache: pnpm + + - name: Install frontend dependencies + run: pnpm install --frozen-lockfile + + - name: Setup Rust compatibility toolchain + uses: dtolnay/rust-toolchain@nightly + with: + toolchain: nightly-2026-07-22 + components: rust-src + + - name: Prepare WebView2 109 fixed runtime + shell: pwsh + run: ./.github/scripts/prepare-webview2-win7-runtime.ps1 + + - name: Prepare Win7 / Server 2012 R2 WebView2 loader + shell: pwsh + run: ./.github/scripts/prepare-webview2-win7-loader.ps1 + + - name: Build frontend + run: pnpm build + + - name: Build DBX compatibility binary + shell: pwsh + run: | + $env:TAURI_CONFIG = Get-Content src-tauri/tauri.webview2-win7-fixed.conf.json -Raw + cargo build --locked --package dbx --release --features custom-protocol --target x86_64-win7-windows-msvc -Z build-std=std,panic_abort + + - name: Audit compatibility PE imports + shell: pwsh + run: ./.github/scripts/assert-win7-pe-compat.ps1 -BinaryPath target/x86_64-win7-windows-msvc/release/dbx.exe + + - name: Bundle Win7 / Server 2012 R2 offline installer + shell: pwsh + run: | + $bundleDir = "target/x86_64-win7-windows-msvc/release/bundle/nsis" + pnpm tauri bundle --bundles nsis --target x86_64-win7-windows-msvc ` + --config src-tauri/tauri.webview2-win7-fixed.conf.json + $installer = Get-ChildItem $bundleDir -Filter "*.exe" | + Sort-Object LastWriteTimeUtc -Descending | + Select-Object -First 1 + if (!$installer) { + throw "Missing Win7 / Server 2012 R2 fixed-runtime installer in $bundleDir" + } + Copy-Item -LiteralPath $installer.FullName ` + -Destination "DBX_${{ github.sha }}_x64-win7-server2012r2-webview2-109-offline-setup.exe" ` + -Force + + - name: Audit installer contents + shell: pwsh + run: | + $installer = Get-ChildItem -Filter "DBX_*_x64-win7-server2012r2-webview2-109-offline-setup.exe" | + Select-Object -First 1 + ./.github/scripts/assert-win7-installer-content.ps1 -InstallerPath $installer.FullName + + - name: Upload Win7 / Server 2012 R2 test installer + uses: actions/upload-artifact@v4 + with: + name: DBX-win7-server2012r2-offline-test + path: DBX_*_x64-win7-server2012r2-webview2-109-offline-setup.exe + if-no-files-found: error + retention-days: 7 + + smoke-test-on-server-2012-r2: + name: Smoke Test Installer on Server 2012 R2 + if: ${{ inputs.run_remote_smoke_test }} + needs: build-win7-server2012r2-offline + runs-on: [self-hosted, Windows, X64, server-2012-r2-controller] + environment: windows-server-2012-r2-testing + timeout-minutes: 30 + steps: + - uses: actions/checkout@v5 + + - name: Download test installer + uses: actions/download-artifact@v5 + with: + name: DBX-win7-server2012r2-offline-test + path: installer + + - name: Install and start DBX on Server 2012 R2 + shell: pwsh + env: + SERVER2012_HOST: ${{ secrets.SERVER2012_HOST }} + SERVER2012_USERNAME: ${{ secrets.SERVER2012_USERNAME }} + SERVER2012_PASSWORD: ${{ secrets.SERVER2012_PASSWORD }} + SERVER2012_USE_SSL: ${{ vars.SERVER2012_USE_SSL }} + run: | + $installer = Get-ChildItem installer -Filter "*.exe" | Select-Object -First 1 + if (!$installer) { + throw "The Win7 / Server 2012 R2 installer artifact is missing." + } + ./.github/scripts/invoke-server2012-remote-validation.ps1 ` + -ComputerName $env:SERVER2012_HOST ` + -UserName $env:SERVER2012_USERNAME ` + -Mode Installer ` + -InstallerPath $installer.FullName + + - name: Upload verified Win7 / Server 2012 R2 installer + uses: actions/upload-artifact@v4 + with: + name: DBX-win7-server2012r2-offline-verified + path: installer/*.exe + if-no-files-found: error + retention-days: 14 diff --git a/docs/lib/downloadLinks.test.ts b/docs/lib/downloadLinks.test.ts index 1f0204339f..1ce177ca3a 100644 --- a/docs/lib/downloadLinks.test.ts +++ b/docs/lib/downloadLinks.test.ts @@ -25,10 +25,10 @@ test("Windows downloads include standard, offline, and Windows 7 installers", () }, { id: "windows-7-offline", - label: "Windows 7 离线安装包", + label: "Windows 7 / Server 2012 R2 离线安装包", description: "内置 WebView2 109 · 仅支持 x64", badge: "旧系统", - href: "https://dl.dbxio.com/releases/v0.5.82/DBX_0.5.82_x64-win7-webview2-109-offline-setup.exe?v=0.5.82", + href: "https://dl.dbxio.com/releases/v0.5.82/DBX_0.5.82_x64-win7-server2012r2-webview2-109-offline-setup.exe?v=0.5.82", }, ], ); diff --git a/docs/lib/downloadLinks.ts b/docs/lib/downloadLinks.ts index afd8f57c19..9259adec2c 100644 --- a/docs/lib/downloadLinks.ts +++ b/docs/lib/downloadLinks.ts @@ -52,10 +52,10 @@ const downloadArtifacts: DownloadArtifact[] = [ { id: "windows-7-offline", iconId: "windows", - labels: { en: "Windows 7 offline installer", cn: "Windows 7 离线安装包" }, + labels: { en: "Windows 7 / Server 2012 R2 offline installer", cn: "Windows 7 / Server 2012 R2 离线安装包" }, descriptions: { en: "Includes WebView2 109 · x64 only", cn: "内置 WebView2 109 · 仅支持 x64" }, badges: { en: "Legacy", cn: "旧系统" }, - suffix: "x64-win7-webview2-109-offline-setup.exe", + suffix: "x64-win7-server2012r2-webview2-109-offline-setup.exe", }, { id: "linux", diff --git a/vendor/wry/src/webview2/mod.rs b/vendor/wry/src/webview2/mod.rs index 5158141f86..60041d5017 100644 --- a/vendor/wry/src/webview2/mod.rs +++ b/vendor/wry/src/webview2/mod.rs @@ -1913,7 +1913,13 @@ pub fn platform_webview_version() -> Result { fn configured_browser_executable_folder() -> Option { let folder = std::env::var_os("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER"); - browser_executable_folder_from(folder.as_deref(), cfg!(target_vendor = "win7")) + let version = windows_version::OsVersion::current(); + let fixed_runtime_enabled = should_use_fixed_runtime( + cfg!(target_vendor = "win7"), + version.major, + version.minor, + ); + browser_executable_folder_from(folder.as_deref(), fixed_runtime_enabled) } /// Builds a structured [`WebView2ProcessFailedInfo`] from the WebView2 event @@ -2058,6 +2064,21 @@ fn browser_executable_folder_from( mod tests { use super::*; + #[test] + fn win7_target_uses_fixed_runtime_on_windows_7() { + assert!(should_use_fixed_runtime(true, 6, 1)); + } + + #[test] + fn compatibility_target_uses_fixed_runtime_on_server_2012_r2() { + assert!(should_use_fixed_runtime(true, 6, 3)); + } + + #[test] + fn standard_windows_target_uses_system_runtime_on_windows_7() { + assert!(!should_use_fixed_runtime(false, 6, 1)); + } + #[test] fn missing_or_empty_browser_folder_uses_system_runtime() { assert!(browser_executable_folder_from(None, true).is_none()); @@ -2154,6 +2175,12 @@ mod tests { #[inline] fn is_windows_7() -> bool { let v = windows_version::OsVersion::current(); - // windows 7 is 6.1 + // Windows 7 的内核版本是 6.1。 v.major == 6 && v.minor == 1 } + +fn should_use_fixed_runtime(is_win7_target: bool, os_major: u32, os_minor: u32) -> bool { + // Windows 7 与 Server 2012 R2 专用离线包都必须使用随包 Runtime, + // 避免旧系统依赖机器级 Evergreen 注册状态。 + is_win7_target && os_major == 6 && matches!(os_minor, 1 | 3) +}