param([Parameter(Mandatory)][string]$BridgeArchive,[Parameter(Mandatory)][string]$FullArchive) $ErrorActionPreference='Stop' Add-Type @' using System; using System.Runtime.InteropServices; public static class UpdateResource { [DllImport("kernel32.dll", CharSet=CharSet.Unicode)] static extern IntPtr LoadLibraryEx(string path, IntPtr file, uint flags); [DllImport("kernel32.dll")] static extern IntPtr FindResource(IntPtr module, IntPtr name, IntPtr type); [DllImport("kernel32.dll")] static extern IntPtr LoadResource(IntPtr module, IntPtr resource); [DllImport("kernel32.dll")] static extern IntPtr LockResource(IntPtr resource); [DllImport("kernel32.dll")] static extern uint SizeofResource(IntPtr module, IntPtr resource); [DllImport("kernel32.dll")] static extern bool FreeLibrary(IntPtr module); public static byte[] Read(string path) { var module=LoadLibraryEx(path,IntPtr.Zero,2|32); if(module==IntPtr.Zero) throw new Exception("Cannot load bridge resources"); try { var resource=FindResource(module,(IntPtr)201,(IntPtr)10); var size=SizeofResource(module,resource); if(size==0 || size>1024*1024) throw new Exception("Invalid bridge updater resource"); var bytes=new byte[size]; Marshal.Copy(LockResource(LoadResource(module,resource)),bytes,0,(int)size); return bytes; } finally { FreeLibrary(module); } } } '@ $root=Join-Path ([IO.Path]::GetTempPath()) ('KSwitcher-transition-'+[guid]::NewGuid().ToString('N')) [IO.Directory]::CreateDirectory($root) | Out-Null try { $legacy=Join-Path $root 'legacy.ps1' $oldSource=git -C (Join-Path $PSScriptRoot '..') show v0.4.1:resources/update.ps1 if ($LASTEXITCODE) { throw 'Cannot read the released v0.4.1 updater.' } $oldSource | Set-Content -LiteralPath $legacy -Encoding utf8 $releases=@('v0.4.2','release-v0.5.0') | ForEach-Object { @{tag_name=$_;draft=$false;prerelease=$false;assets=@( @{name='KSwitcher-win-x64.zip';browser_download_url="https://gitea.hrynco.com/hrynco/hrynco-kswitcher/releases/download/$_/KSwitcher-win-x64.zip"}, @{name='SHA256SUMS.txt';browser_download_url="https://gitea.hrynco.com/hrynco/hrynco-kswitcher/releases/download/$_/SHA256SUMS.txt"})} } $install=Join-Path $root 'install' [IO.Directory]::CreateDirectory((Join-Path $install 'data')) | Out-Null [IO.Directory]::CreateDirectory((Join-Path $install 'dictionaries')) | Out-Null [IO.File]::WriteAllText((Join-Path $install 'data/settings.json'),'personal settings') [IO.File]::WriteAllText((Join-Path $install 'dictionaries/en.txt'),'personal dictionary') & { . $legacy -Library $selected=Select-Release $releases ([version]'0.4.1') if ($selected.version -ne 'v0.4.2') { throw 'Legacy client skipped the bridge.' } $stage=Join-Path $root 'bridge-stage' Expand-Release $BridgeArchive $stage ([version]'0.4.2') $changed=[Collections.Generic.List[string]]::new() Install-Files $stage $install (Join-Path $root 'bridge-backup') $changed } $bridgeHelper=Join-Path $root 'bridge-helper.ps1' [IO.File]::WriteAllBytes($bridgeHelper,[UpdateResource]::Read((Join-Path $install 'KSwitcher.exe'))) . $bridgeHelper -Library $selected=Select-Release $releases ([version]'0.4.2') if ($selected.version -ne 'release-v0.5.0') { throw 'Bridge did not find the full release.' } $stage=Join-Path $root 'full-stage' Expand-Release $FullArchive $stage ([version]'0.5.0') $changed=[Collections.Generic.List[string]]::new() Install-Files $stage $install (Join-Path $root 'full-backup') $changed foreach ($name in @('KSwitcher.exe','KSwitcher.Config.exe','KSwitcher.Screenshot.exe')) { $version=[Diagnostics.FileVersionInfo]::GetVersionInfo((Join-Path $install $name)).FileVersion if ((Get-StableVersion $version) -ne [version]'0.5.0') { throw "Incorrect installed version: $name" } } if ([IO.File]::ReadAllText((Join-Path $install 'data/settings.json')) -ne 'personal settings' -or [IO.File]::ReadAllText((Join-Path $install 'dictionaries/en.txt')) -ne 'personal dictionary') { throw 'User data changed during transition.' } if (Select-Release $releases ([version]'0.5.0')) { throw 'Current version offers another update.' } Undo-Files $install (Join-Path $root 'full-backup') $changed if ((Get-StableVersion ([Diagnostics.FileVersionInfo]::GetVersionInfo((Join-Path $install 'KSwitcher.exe')).FileVersion)) -ne [version]'0.4.2' -or (Test-Path -LiteralPath (Join-Path $install 'KSwitcher.Screenshot.exe'))) { throw 'Full release rollback did not restore the bridge.' } 'Passed real-package transition: v0.4.1 updater -> v0.4.2 bridge -> release-v0.5.0; user data preserved; rollback verified.' } finally { if ([IO.Path]::GetDirectoryName($root) -eq [IO.Path]::GetTempPath().TrimEnd('\') -and (Split-Path -Leaf $root) -like 'KSwitcher-transition-*') { Remove-Item -LiteralPath $root -Recurse -Force } }