Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Windows/MAS/Separate-Files-Version/Change_Edition.cmd
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1042 lines (812 sloc)
34 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@setlocal DisableDelayedExpansion | |
@echo off | |
::============================================================================ | |
:: | |
:: This script is a part of 'Microsoft_Activation_Scripts' (MAS) project. | |
:: | |
:: Homepage: massgrave.dev | |
:: Email: windowsaddict@protonmail.com | |
:: | |
::============================================================================ | |
:: To stage current edition while changing edition with CBS Upgrade Method, change 0 to 1 in below line | |
set _stg=0 | |
::======================================================================================================================================== | |
:: Re-launch the script with x64 process if it was initiated by x86 process on x64 bit Windows | |
:: or with ARM64 process if it was initiated by x86/ARM32 process on ARM64 Windows | |
set "_cmdf=%~f0" | |
for %%# in (%*) do ( | |
if /i "%%#"=="r1" set r1=1 | |
if /i "%%#"=="r2" set r2=1 | |
) | |
if exist %SystemRoot%\Sysnative\cmd.exe if not defined r1 ( | |
setlocal EnableDelayedExpansion | |
start %SystemRoot%\Sysnative\cmd.exe /c ""!_cmdf!" %* r1" | |
exit /b | |
) | |
:: Re-launch the script with ARM32 process if it was initiated by x64 process on ARM64 Windows | |
if exist %SystemRoot%\SysArm32\cmd.exe if %PROCESSOR_ARCHITECTURE%==AMD64 if not defined r2 ( | |
setlocal EnableDelayedExpansion | |
start %SystemRoot%\SysArm32\cmd.exe /c ""!_cmdf!" %* r2" | |
exit /b | |
) | |
:: Set Path variable, it helps if it is misconfigured in the system | |
set "PATH=%SystemRoot%\System32;%SystemRoot%\System32\wbem;%SystemRoot%\System32\WindowsPowerShell\v1.0\" | |
if exist "%SystemRoot%\Sysnative\reg.exe" ( | |
set "PATH=%SystemRoot%\Sysnative;%SystemRoot%\Sysnative\wbem;%SystemRoot%\Sysnative\WindowsPowerShell\v1.0\;%PATH%" | |
) | |
:: Check LF line ending | |
pushd "%~dp0" | |
>nul findstr /rxc:".*" "%~nx0" | |
if not %errorlevel%==0 ( | |
echo: | |
echo Error: Script either has LF line ending issue, or it failed to read itself. | |
echo: | |
ping 127.0.0.1 -n 6 > nul | |
popd | |
exit /b | |
) | |
popd | |
::======================================================================================================================================== | |
cls | |
color 07 | |
title Change Windows Edition | |
set _elev= | |
if /i "%~1"=="-el" set _elev=1 | |
set winbuild=1 | |
set "nul=>nul 2>&1" | |
set psc=powershell.exe | |
for /f "tokens=6 delims=[]. " %%G in ('ver') do set winbuild=%%G | |
set _NCS=1 | |
if %winbuild% LSS 10586 set _NCS=0 | |
if %winbuild% GEQ 10586 reg query "HKCU\Console" /v ForceV2 2>nul | find /i "0x0" 1>nul && (set _NCS=0) | |
if %_NCS% EQU 1 ( | |
for /F %%a in ('echo prompt $E ^| cmd') do set "esc=%%a" | |
set "Red="41;97m"" | |
set "Gray="100;97m"" | |
set "Green="42;97m"" | |
set "Magenta="45;97m"" | |
set "_White="40;37m"" | |
set "_Green="40;92m"" | |
set "_Yellow="40;93m"" | |
) else ( | |
set "Red="Red" "white"" | |
set "Gray="Darkgray" "white"" | |
set "Green="DarkGreen" "white"" | |
set "Magenta="Darkmagenta" "white"" | |
set "_White="Black" "Gray"" | |
set "_Green="Black" "Green"" | |
set "_Yellow="Black" "Yellow"" | |
) | |
set "nceline=echo: &echo ==== ERROR ==== &echo:" | |
set "eline=echo: &call :dk_color %Red% "==== ERROR ====" &echo:" | |
set "line=echo ___________________________________________________________________________________________" | |
if %~z0 GEQ 200000 (set "_exitmsg=Go back") else (set "_exitmsg=Exit") | |
::======================================================================================================================================== | |
if %winbuild% LSS 7600 ( | |
%nceline% | |
echo Unsupported OS version detected. | |
echo Project is supported only for Windows 7/8/8.1/10/11 and their Server equivalent. | |
goto ced_done | |
) | |
for %%# in (powershell.exe) do @if "%%~$PATH:#"=="" ( | |
%nceline% | |
echo Unable to find powershell.exe in the system. | |
goto ced_done | |
) | |
::======================================================================================================================================== | |
:: Fix for the special characters limitation in path name | |
set "_work=%~dp0" | |
if "%_work:~-1%"=="\" set "_work=%_work:~0,-1%" | |
set "_batf=%~f0" | |
set "_batp=%_batf:'=''%" | |
set _PSarg="""%~f0""" -el %_args% | |
set "_ttemp=%temp%" | |
setlocal EnableDelayedExpansion | |
::======================================================================================================================================== | |
echo "!_batf!" | find /i "!_ttemp!" 1>nul && ( | |
if /i not "!_work!"=="!_ttemp!" ( | |
%eline% | |
echo Script is launched from the temp folder, | |
echo Most likely you are running the script directly from the archive file. | |
echo: | |
echo Extract the archive file and launch the script from the extracted folder. | |
goto ced_done | |
) | |
) | |
::======================================================================================================================================== | |
:: Elevate script as admin and pass arguments and preventing loop | |
>nul fltmc || ( | |
if not defined _elev %nul% %psc% "start cmd.exe -arg '/c \"!_PSarg:'=''!\"' -verb runas" && exit /b | |
%eline% | |
echo This script require administrator privileges. | |
echo To do so, right click on this script and select 'Run as administrator'. | |
goto ced_done | |
) | |
::======================================================================================================================================== | |
cls | |
mode 98, 30 | |
echo: | |
echo Initializing... | |
echo: | |
call :dk_product | |
call :dk_ckeckwmic | |
:: Show info for potential script stuck scenario | |
sc start sppsvc %nul% | |
if %errorlevel% NEQ 1056 if %errorlevel% NEQ 0 ( | |
echo: | |
echo Error code: %errorlevel% | |
call :dk_color %Red% "Failed to start [sppsvc] service, rest of the process may take a long time..." | |
echo: | |
) | |
::======================================================================================================================================== | |
:: Check Activation IDs | |
call :dk_actids | |
if not defined applist ( | |
%eline% | |
echo Activation IDs not found. Aborting... | |
echo: | |
echo Check this page for help. https://massgrave.dev/troubleshoot | |
goto ced_done | |
) | |
:: Check Windows Edition | |
set osedition= | |
for /f "tokens=3 delims=: " %%a in ('DISM /English /Online /Get-CurrentEdition 2^>nul ^| find /i "Current Edition :"') do set "osedition=%%a" | |
if "%osedition%"=="" ( | |
%eline% | |
DISM /English /Online /Get-CurrentEdition %nul% | |
cmd /c exit /b !errorlevel! | |
echo DISM command failed [Error Code - 0x!=ExitCode!] | |
echo OS Edition was not detected properly. Aborting... | |
echo: | |
echo Check this page for help. https://massgrave.dev/troubleshoot | |
goto ced_done | |
) | |
:: Check SKU value | |
set osSKU= | |
set regSKU= | |
set wmiSKU= | |
for /f "tokens=3 delims=." %%a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\ProductOptions" /v OSProductPfn 2^>nul') do set "regSKU=%%a" | |
if %_wmic% EQU 1 for /f "tokens=2 delims==" %%a in ('"wmic Path Win32_OperatingSystem Get OperatingSystemSKU /format:LIST" 2^>nul') do if not errorlevel 1 set "wmiSKU=%%a" | |
if %_wmic% EQU 0 for /f "tokens=1" %%a in ('%psc% "([WMI]'Win32_OperatingSystem=@').OperatingSystemSKU" 2^>nul') do if not errorlevel 1 set "wmiSKU=%%a" | |
set osSKU=%wmiSKU% | |
if not defined osSKU set osSKU=%regSKU% | |
if not defined osSKU ( | |
%eline% | |
echo SKU value was not detected properly. Aborting... | |
goto ced_done | |
) | |
set branch= | |
for /f "skip=2 tokens=2*" %%a in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v BuildBranch 2^>nul') do set "branch=%%b" | |
:: Check PowerShell | |
%psc% $ExecutionContext.SessionState.LanguageMode 2>nul | find /i "Full" 1>nul || ( | |
%eline% | |
echo PowerShell is not responding properly. Aborting... | |
goto ced_done | |
) | |
::======================================================================================================================================== | |
:: Get Target editions list | |
set _target= | |
set _dtarget= | |
set _ptarget= | |
set _ntarget= | |
if %winbuild% GEQ 10240 for /f "tokens=4" %%a in ('dism /online /english /Get-TargetEditions ^| findstr /i /c:"Target Edition : "') do (if defined _dtarget (set "_dtarget=!_dtarget! %%a") else (set "_dtarget=%%a")) | |
for /f "tokens=4" %%a in ('%psc% "$f=[io.file]::ReadAllText('!_batp!') -split ':cbsxml\:.*';& ([ScriptBlock]::Create($f[1])) -GetTargetEditions;" ^| findstr /i /c:"Target Edition : "') do (if defined _ptarget (set "_ptarget=!_ptarget! %%a") else (set "_ptarget=%%a")) | |
::======================================================================================================================================== | |
:: Block the change to/from CountrySpecific and CloudEdition editions | |
for %%# in (99 139 202 203) do if %osSKU%==%%# ( | |
%eline% | |
echo [%winos% ^| SKU:%osSKU% ^| %winbuild%] | |
echo It's not recommended to change this installed edition to any other. | |
echo Aborting... | |
goto ced_done | |
) | |
for %%# in ( %_dtarget% %_ptarget% ) do ( | |
echo "!_target!" | find /i " %%# " 1>nul || set "_target=!_target! %%# " | |
) | |
if defined _target ( | |
for %%# in (%_target%) do ( | |
echo %%# | findstr /i "CountrySpecific CloudEdition" %nul% || (set "_ntarget=!_ntarget! %%#") | |
) | |
) | |
if not defined _ntarget ( | |
%line% | |
echo: | |
call :dk_color %Gray% "Target Edition not found." | |
echo Current Edition [%osedition% ^| %winbuild%] can not be changed to any other Edition. | |
%line% | |
goto ced_done | |
) | |
::======================================================================================================================================== | |
:cedmenu2 | |
cls | |
mode 98, 30 | |
set inpt= | |
set note= | |
set counter=0 | |
set verified=0 | |
set targetedition= | |
%line% | |
echo: | |
call :dk_color %Gray% "You can change the Edition [%osedition%] [%winbuild%] to one of the following." | |
%line% | |
echo: | |
for %%A in (%_ntarget%) do ( | |
set /a counter+=1 | |
if %winbuild% GEQ 10240 ( | |
echo "%_ptarget%" | find /i "%%A" 1>nul && ( | |
set note=1 | |
call :dk_color2 %_White% "[!counter!] " %Magenta% "%%A" | |
) || ( | |
echo [!counter!] %%A | |
) | |
) else ( | |
echo [!counter!] %%A | |
) | |
set targetedition!counter!=%%A | |
) | |
%line% | |
echo: | |
echo [0] %_exitmsg% | |
echo: | |
if defined note ( | |
echo Note: CBS Upgrade Method is available for Purple colored editions. | |
echo: | |
) | |
call :dk_color %_Green% "Enter option number in keyboard, and press "Enter":" | |
set /p inpt= | |
if "%inpt%"=="" goto cedmenu2 | |
if "%inpt%"=="0" exit /b | |
for /l %%i in (1,1,%counter%) do (if "%inpt%"=="%%i" set verified=1) | |
set targetedition=!targetedition%inpt%! | |
if %verified%==0 goto cedmenu2 | |
::======================================================================================================================================== | |
cls | |
if %winbuild% GEQ 10240 ( | |
echo "%_ptarget%" | find /i "%targetedition%" 1>nul && ( | |
echo "%_dtarget%" | find /i "%targetedition%" 1>nul && ( | |
echo: | |
%line% | |
echo: | |
if exist "%SystemRoot%\Servicing\Packages\Microsoft-Windows-Server*Edition~*.mum" ( | |
echo [1] DISM Method [Recommended] | |
) else ( | |
echo [1] Changepk Method [Recommended] | |
) | |
echo: | |
echo [2] CBS Upgrade Method [Alternative] | |
echo: | |
echo [0] Go back | |
%line% | |
echo: | |
echo Enter a menu option in the Keyboard: | |
choice /C:120 /N | |
set _el=!errorlevel! | |
if !_el!==3 goto :cedmenu2 | |
if !_el!==2 goto :cbsmethod | |
if !_el!==1 REM | |
) | |
) | |
) else ( | |
goto :cbsmethod | |
) | |
echo "%_ptarget%" | find /i "%targetedition%" 1>nul && ( | |
echo "%_dtarget%" | find /i "%targetedition%" 1>nul || ( | |
goto :cbsmethod | |
) | |
) | |
if exist "%SystemRoot%\Servicing\Packages\Microsoft-Windows-Server*Edition~*.mum" ( | |
goto :ced_change_server | |
) | |
cls | |
set key= | |
set _chan= | |
set _changepk=0 | |
:: Check if changepk.exe or slmgr.vbs is required for edition upgrade | |
if not exist "%SystemRoot%\System32\spp\tokens\skus\%targetedition%\" ( | |
set _changepk=1 | |
) | |
if /i "%osedition:~0,4%"=="Core" ( | |
if /i not "%targetedition:~0,4%"=="Core" ( | |
set _changepk=1 | |
) | |
) | |
if %_changepk%==1 ( | |
set "keyflow=Retail Volume:MAK Volume:GVLK OEM:NONSLP OEM:DM" | |
) else ( | |
set "keyflow=Retail OEM:NONSLP OEM:DM Volume:MAK Volume:GVLK" | |
) | |
if not defined key call :ced_targetSKU %targetedition% | |
if not defined key if defined targetSKU call :ced_windowskey | |
if defined key if defined pkeychannel set _chan=%pkeychannel% | |
if not defined key call :changeeditiondata | |
if not defined key ( | |
%eline% | |
echo [%targetedition% ^| %winbuild%] | |
echo Unable to get product key from pkeyhelper.dll | |
echo Make sure you are using updated version of the script. | |
echo https://massgrave.dev | |
goto ced_done | |
) | |
::======================================================================================================================================== | |
%line% | |
:: Changing from Core to Non-Core & Changing editions in Windows build older than 17134 requires "changepk /productkey" method and restart | |
:: In other cases, editions can be changed instantly with "slmgr /ipk" | |
cls | |
if %_changepk%==1 ( | |
echo "%_chan%" | find /i "OEM" >NUL && ( | |
%eline% | |
echo [%osedition%] can not be changed to [%targetedition%] Edition due to lack of non OEM keys. | |
echo Non-OEM keys are required to change from Core to Non-Core Editions. | |
goto ced_done | |
) | |
) | |
:ced_loop | |
cls | |
if %_changepk%==1 ( | |
for %%a in (l.root-servers.net resolver1.opendns.com download.windowsupdate.com google.com) do ( | |
for /f "delims=[] tokens=2" %%# in ('ping -n 1 %%a') do ( | |
if not [%%#]==[] ( | |
%eline% | |
echo Internet needs to be disconnected to change edition [%osedition%] to [%targetedition%] | |
echo Disconnect the Internet and then press any key... | |
pause >nul | |
goto ced_loop | |
) | |
) | |
) | |
) | |
echo: | |
echo Changing the Current Edition [%osedition%] to [%targetedition%] | |
echo: | |
if %_changepk%==1 ( | |
call :dk_color %Magenta% "Notes-" | |
echo: | |
echo - You can safely ignore if error appears in the upgrade Window, | |
echo but in that case you must manually reboot the system. | |
echo: | |
echo - Save your work before continue, system will auto restart. | |
echo - You can connect to Internet after the system restart. | |
echo: | |
echo - You will need to activate with HWID option once the edition is changed. | |
echo: | |
choice /C:21 /N /M "[1] Continue [2] %_exitmsg% : " | |
if !errorlevel!==1 exit /b | |
) | |
::======================================================================================================================================== | |
if %_changepk%==0 ( | |
echo Installing %_chan% Key [%key%] | |
echo: | |
if %_wmic% EQU 1 wmic path SoftwareLicensingService where __CLASS='SoftwareLicensingService' call InstallProductKey ProductKey="%key%" %nul% | |
if %_wmic% EQU 0 %psc% "(([WMISEARCHER]'SELECT Version FROM SoftwareLicensingService').Get()).InstallProductKey('%key%')" %nul% | |
if not !errorlevel!==0 cscript //nologo %windir%\system32\slmgr.vbs /ipk %key% %nul% | |
set error_code=!errorlevel! | |
cmd /c exit /b !error_code! | |
if !error_code! NEQ 0 set "error_code=[0x!=ExitCode!]" | |
if !error_code! EQU 0 ( | |
call :dk_refresh | |
call :dk_color %Green% "[Successful]" | |
echo: | |
call :dk_color %Gray% "Reboot is required to properly change the Edition." | |
) else ( | |
call :dk_color %Red% "[Unsuccessful] [Error Code: 0x!=ExitCode!]" | |
) | |
) | |
if %_changepk%==1 ( | |
echo: | |
echo Applying the command with %_chan% Key | |
echo start changepk.exe /ProductKey %key% | |
start changepk.exe /ProductKey %key% | |
) | |
%line% | |
goto ced_done | |
::======================================================================================================================================== | |
:cbsmethod | |
cls | |
mode con cols=105 lines=32 | |
%nul% %psc% "&{$W=$Host.UI.RawUI.WindowSize;$B=$Host.UI.RawUI.BufferSize;$W.Height=31;$B.Height=200;$Host.UI.RawUI.WindowSize=$W;$Host.UI.RawUI.BufferSize=$B;}" | |
echo: | |
echo Changing the Current Edition [%osedition%] to [%targetedition%] | |
echo: | |
call :dk_color %Magenta% "Important - Save your work before continue, system will auto reboot." | |
if %winbuild% GEQ 17034 if %targetedition%==Professional echo - Enterprise Key will be installed instead of Pro, you can quickly change to Pro later. | |
echo: | |
choice /C:01 /N /M "[1] Continue [0] %_exitmsg% : " | |
if %errorlevel%==1 exit /b | |
echo: | |
echo Initializing... | |
echo: | |
if %_stg%==0 (set stage=) else (set stage=-StageCurrent) | |
%psc% "$f=[io.file]::ReadAllText('!_batp!') -split ':cbsxml\:.*';& ([ScriptBlock]::Create($f[1])) -SetEdition %targetedition% %stage%;" | |
echo: | |
%line% | |
goto ced_done | |
::======================================================================================================================================== | |
:ced_change_server | |
cls | |
mode con cols=105 lines=32 | |
%nul% %psc% "&{$W=$Host.UI.RawUI.WindowSize;$B=$Host.UI.RawUI.BufferSize;$W.Height=31;$B.Height=200;$Host.UI.RawUI.WindowSize=$W;$Host.UI.RawUI.BufferSize=$B;}" | |
set key= | |
set pkeychannel= | |
set "keyflow=Volume:GVLK Retail Volume:MAK OEM:NONSLP OEM:DM" | |
call :changeeditionserverdata | |
if not defined key call :ced_targetSKU %targetedition% | |
if not defined key if defined targetSKU call :ced_windowskey | |
if defined key if not defined pkeychannel call :dk_pkeychannel %key% | |
if not defined key ( | |
%eline% | |
echo [%targetedition% ^| %winbuild%] | |
echo Unable to get product key from pkeyhelper.dll | |
echo Make sure you are using updated version of the script. | |
echo https://massgrave.dev | |
goto ced_done | |
) | |
::======================================================================================================================================== | |
cls | |
echo: | |
echo Changing the Current Edition [%osedition%] to [%targetedition%] | |
echo: | |
echo Applying the command with %pkeychannel% Key | |
echo DISM /online /Set-Edition:%targetedition% /ProductKey:%key% /AcceptEula | |
DISM /online /Set-Edition:%targetedition% /ProductKey:%key% /AcceptEula | |
call :dk_color %Magenta% "Make sure to restart the system." | |
::======================================================================================================================================== | |
:ced_done | |
echo: | |
call :dk_color %_Yellow% "Press any key to %_exitmsg%..." | |
pause >nul | |
exit /b | |
::======================================================================================================================================== | |
:: Refresh license status | |
:dk_refresh | |
if %_wmic% EQU 1 wmic path SoftwareLicensingService where __CLASS='SoftwareLicensingService' call RefreshLicenseStatus %nul% | |
if %_wmic% EQU 0 %psc% "$null=(([WMICLASS]'SoftwareLicensingService').GetInstances()).RefreshLicenseStatus()" %nul% | |
exit /b | |
:: Get Windows Activation IDs | |
:dk_actids | |
set applist= | |
if %_wmic% EQU 1 set "chkapp=for /f "tokens=2 delims==" %%a in ('"wmic path SoftwareLicensingProduct where (ApplicationID='55c92734-d682-4d71-983e-d6ec3f16059f') get ID /VALUE" 2^>nul')" | |
if %_wmic% EQU 0 set "chkapp=for /f "tokens=2 delims==" %%a in ('%psc% "(([WMISEARCHER]'SELECT ID FROM SoftwareLicensingProduct WHERE ApplicationID=''55c92734-d682-4d71-983e-d6ec3f16059f''').Get()).ID ^| %% {echo ('ID='+$_)}" 2^>nul')" | |
%chkapp% do (if defined applist (call set "applist=!applist! %%a") else (call set "applist=%%a")) | |
exit /b | |
:: Check wmic.exe | |
:dk_ckeckwmic | |
set _wmic=0 | |
for %%# in (wmic.exe) do @if not "%%~$PATH:#"=="" ( | |
wmic path Win32_ComputerSystem get CreationClassName /value 2>nul | find /i "computersystem" 1>nul && set _wmic=1 | |
) | |
exit /b | |
:: Get Product name (WMI/REG methods are not reliable in all conditions, hence winbrand.dll method is used) | |
:dk_product | |
call :dk_reflection | |
set d1=%ref% $meth = $TypeBuilder.DefinePInvokeMethod('BrandingFormatString', 'winbrand.dll', 'Public, Static', 1, [String], @([String]), 1, 3); | |
set d1=%d1% $meth.SetImplementationFlags(128); $TypeBuilder.CreateType()::BrandingFormatString('%%WINDOWS_LONG%%') | |
set winos= | |
for /f "delims=" %%s in ('"%psc% %d1%"') do if not errorlevel 1 (set winos=%%s) | |
echo "%winos%" | find /i "Windows" 1>nul || ( | |
for /f "skip=2 tokens=2*" %%a in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName 2^>nul') do set "winos=%%b" | |
if %winbuild% GEQ 22000 ( | |
set winos=!winos:Windows 10=Windows 11! | |
) | |
) | |
exit /b | |
:: Common lines used in PowerShell reflection code | |
:dk_reflection | |
set ref=$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly(4, 1); | |
set ref=%ref% $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule(2, $False); | |
set ref=%ref% $TypeBuilder = $ModuleBuilder.DefineType(0); | |
exit /b | |
::======================================================================================================================================== | |
:: Get Product Key from pkeyhelper.dll for future new editions | |
:: It works on Windows 10 1803 (17134) and later builds. | |
:dk_pkey | |
call :dk_reflection | |
set d1=%ref% [void]$TypeBuilder.DefinePInvokeMethod('SkuGetProductKeyForEdition', 'pkeyhelper.dll', 'Public, Static', 1, [int], @([int], [String], [String].MakeByRefType(), [String].MakeByRefType()), 1, 3); | |
set d1=%d1% $out = ''; [void]$TypeBuilder.CreateType()::SkuGetProductKeyForEdition(%1, %2, [ref]$out, [ref]$null); $out | |
set pkey= | |
for /f %%a in ('%psc% "%d1%"') do if not errorlevel 1 (set pkey=%%a) | |
exit /b | |
:: Get channel name for the key which was extracted from pkeyhelper.dll | |
:dk_pkeychannel | |
set k=%1 | |
set m=[Runtime.InteropServices.Marshal] | |
set p=%SystemRoot%\System32\spp\tokens\pkeyconfig\pkeyconfig.xrm-ms | |
set d1=%ref% [void]$TypeBuilder.DefinePInvokeMethod('PidGenX', 'pidgenx.dll', 'Public, Static', 1, [int], @([String], [String], [String], [int], [IntPtr], [IntPtr], [IntPtr]), 1, 3); | |
set d1=%d1% $r = [byte[]]::new(0x04F8); $r[0] = 0xF8; $r[1] = 0x04; $f = %m%::AllocHGlobal(0x04F8); %m%::Copy($r, 0, $f, 0x04F8); | |
set d1=%d1% [void]$TypeBuilder.CreateType()::PidGenX('%k%', '%p%', '00000', 0, 0, 0, $f); %m%::Copy($f, $r, 0, 0x04F8); %m%::FreeHGlobal($f); [Text.Encoding]::Unicode.GetString($r, 1016, 128) | |
set pkeychannel= | |
for /f %%a in ('%psc% "%d1%"') do if not errorlevel 1 (set pkeychannel=%%a) | |
exit /b | |
:ced_windowskey | |
for %%# in (pkeyhelper.dll) do @if "%%~$PATH:#"=="" exit /b | |
for %%# in (%keyflow%) do ( | |
call :dk_pkey %targetSKU% '%%#' | |
if defined pkey call :dk_pkeychannel !pkey! | |
if /i [!pkeychannel!]==[%%#] ( | |
set key=!pkey! | |
exit /b | |
) | |
) | |
exit /b | |
::======================================================================================================================================== | |
:ced_targetSKU | |
set k=%1 | |
set targetSKU= | |
for %%# in (pkeyhelper.dll) do @if "%%~$PATH:#"=="" exit /b | |
call :dk_reflection | |
set d1=%ref% [void]$TypeBuilder.DefinePInvokeMethod('GetEditionIdFromName', 'pkeyhelper.dll', 'Public, Static', 1, [int], @([String], [int].MakeByRefType()), 1, 3); | |
set d1=%d1% $out = 0; [void]$TypeBuilder.CreateType()::GetEditionIdFromName('%k%', [ref]$out); $out | |
for /f %%a in ('%psc% "%d1%"') do if not errorlevel 1 (set targetSKU=%%a) | |
if "%targetSKU%"=="0" set targetSKU= | |
exit /b | |
::======================================================================================================================================== | |
:dk_color | |
if %_NCS% EQU 1 ( | |
echo %esc%[%~1%~2%esc%[0m | |
) else ( | |
%psc% write-host -back '%1' -fore '%2' '%3' | |
) | |
exit /b | |
:dk_color2 | |
if %_NCS% EQU 1 ( | |
echo %esc%[%~1%~2%esc%[%~3%~4%esc%[0m | |
) else ( | |
%psc% write-host -back '%1' -fore '%2' '%3' -NoNewline; write-host -back '%4' -fore '%5' '%6' | |
) | |
exit /b | |
::======================================================================================================================================== | |
:: https://github.com/Gamers-Against-Weed/Set-WindowsCbsEdition | |
:cbsxml:[ | |
param ( | |
[Parameter()] | |
[String]$SetEdition, | |
[Parameter()] | |
[Switch]$GetTargetEditions, | |
[Parameter()] | |
[Switch]$StageCurrent | |
) | |
function Get-AssemblyIdentity { | |
param ( | |
[String]$PackageName | |
) | |
$PackageName = [String]$PackageName | |
$packageData = ($PackageName -split '~') | |
if($packageData[3] -eq '') { | |
$packageData[3] = 'neutral' | |
} | |
return "<assemblyIdentity name=`"$($packageData[0])`" version=`"$($packageData[4])`" processorArchitecture=`"$($packageData[2])`" publicKeyToken=`"$($packageData[1])`" language=`"$($packageData[3])`" />" | |
} | |
function Get-SxsName { | |
param ( | |
[String]$PackageName | |
) | |
$name = ($PackageName -replace '[^A-z0-9\-\._]', '') | |
if($name.Length -gt 40) { | |
$name = ($name[0..18] -join '') + '\.\.' + ($name[-19..-1] -join '') | |
} | |
return $name.ToLower() | |
} | |
function Find-EditionXmlInSxs { | |
param ( | |
[String]$Edition | |
) | |
$candidates = @($Edition, 'Client', 'Server') | |
$winSxs = $Env:SystemRoot + '\WinSxS' | |
$allInSxs = Get-ChildItem -Path $winSxs | select Name | |
foreach($candidate in $candidates) { | |
$name = Get-SxsName -PackageName "Microsoft-Windows-Editions-$candidate" | |
$packages = $allInSxs | where name -Match ('^.*_'+$name+'_31bf3856ad364e35') | |
if($packages.Length -eq 0) { | |
continue | |
} | |
$package = $packages[-1].Name | |
$testPath = $winSxs + "\$package\" + $Edition + 'Edition.xml' | |
if(Test-Path -Path $testPath -PathType Leaf) { | |
return $testPath | |
} | |
} | |
return $null | |
} | |
function Find-EditionXml { | |
param ( | |
[String]$Edition | |
) | |
$servicingEditions = $Env:SystemRoot + '\servicing\Editions' | |
$editionXml = $Edition + 'Edition.xml' | |
$editionXmlInServicing = $servicingEditions + '\' + $editionXml | |
if(Test-Path -Path $editionXmlInServicing -PathType Leaf) { | |
return $editionXmlInServicing | |
} | |
return Find-EditionXmlInSxs -Edition $Edition | |
} | |
function Write-UpgradeCandidates { | |
param ( | |
[HashTable]$InstallCandidates | |
) | |
$editionCount = 0 | |
Write-Host 'Editions that can be upgraded to:' | |
foreach($candidate in $InstallCandidates.Keys) { | |
Write-Host "Target Edition : $candidate" | |
$editionCount++ | |
} | |
if($editionCount -eq 0) { | |
Write-Host '(no editions are available)' | |
} | |
} | |
function Write-UpgradeXml { | |
param ( | |
[Array]$RemovalCandidates, | |
[Array]$InstallCandidates, | |
[Boolean]$Stage | |
) | |
$removeAction = 'remove' | |
if($Stage) { | |
$removeAction = 'stage' | |
} | |
Write-Output '<?xml version="1.0"?>' | |
Write-Output '<unattend xmlns="urn:schemas-microsoft-com:unattend">' | |
Write-Output '<servicing>' | |
foreach($package in $InstallCandidates) { | |
Write-Output '<package action="install">' | |
Write-Output (Get-AssemblyIdentity -PackageName $package) | |
Write-Output '</package>' | |
} | |
foreach($package in $RemovalCandidates) { | |
Write-Output "<package action=`"$removeAction`">" | |
Write-Output (Get-AssemblyIdentity -PackageName $package) | |
Write-Output '</package>' | |
} | |
Write-Output '</servicing>' | |
Write-Output '</unattend>' | |
} | |
function Write-Usage { | |
Get-Help $script:MyInvocation.MyCommand.Path -detailed | |
} | |
$version = '1.0' | |
$getTargetsParam = $GetTargetEditions.IsPresent | |
$stageCurrentParam = $StageCurrent.IsPresent | |
if($SetEdition -eq '' -and ($false -eq $getTargetsParam)) { | |
Write-Usage | |
Exit 1 | |
} | |
$removalCandidates = @(); | |
$installCandidates = @{}; | |
$packages = Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages' | select Name | where { $_.name -match '^.*\\Microsoft-Windows-.*Edition~' } | |
foreach($package in $packages) { | |
$state = (Get-ItemProperty -Path "Registry::$($package.Name)").CurrentState | |
$packageName = ($package.Name -split '\\')[-1] | |
$packageEdition = (($packageName -split 'Edition~')[0] -split 'Microsoft-Windows-')[-1] | |
if($state -eq 0x40) { | |
if($null -eq $installCandidates[$packageEdition]) { | |
$installCandidates[$packageEdition] = @() | |
} | |
if($false -eq ($installCandidates[$packageEdition] -contains $packageName)) { | |
$installCandidates[$packageEdition] = $installCandidates[$packageEdition] + @($packageName) | |
} | |
} | |
if((($state -eq 0x50) -or ($state -eq 0x70)) -and ($false -eq ($removalCandidates -contains $packageName))) { | |
$removalCandidates = $removalCandidates + @($packageName) | |
} | |
} | |
if($getTargetsParam) { | |
Write-UpgradeCandidates -InstallCandidates $installCandidates | |
Exit | |
} | |
if($false -eq ($installCandidates.Keys -contains $SetEdition)) { | |
Write-Error "The system cannot be upgraded to `"$SetEdition`"" | |
Exit 1 | |
} | |
$xmlPath = $Env:SystemRoot + '\Temp' + '\CbsUpgrade.xml' | |
Write-UpgradeXml -RemovalCandidates $removalCandidates ` | |
-InstallCandidates $installCandidates[$SetEdition] ` | |
-Stage $stageCurrentParam >$xmlPath | |
$editionXml = Find-EditionXml -Edition $SetEdition | |
if($null -eq $editionXml) { | |
Write-Warning 'Unable to find edition specific settings XML. Proceeding without it...' | |
} | |
Write-Host 'Starting the upgrade process. This may take a while...' | |
DISM.EXE /English /NoRestart /Online /Apply-Unattend:$xmlPath | |
$dismError = $LASTEXITCODE | |
Remove-Item -Path $xmlPath -Force | |
if(($dismError -ne 0) -and ($dismError -ne 3010)) { | |
Write-Error 'Failed to upgrade to the target edition' | |
Exit $dismError | |
} | |
if($null -ne $editionXml) { | |
$destination = $Env:SystemRoot + '\' + $SetEdition + '.xml' | |
Copy-Item -Path $editionXml -Destination $destination | |
DISM.EXE /English /NoRestart /Online /Apply-Unattend:$editionXml | |
$dismError = $LASTEXITCODE | |
if(($dismError -ne 0) -and ($dismError -ne 3010)) { | |
Write-Error 'Failed to apply edition specific settings' | |
Exit $dismError | |
} | |
} | |
Restart-Computer | |
:cbsxml:] | |
::======================================================================================================================================== | |
:: 1st column = Generic Retail/OEM/MAK/GVLK Key | |
:: 2nd column = Key Type | |
:: 3rd column = WMI Edition ID | |
:: 4th column = Version name incase same Edition ID is used in different OS versions with different key | |
:: Separator = _ | |
:: Key preference is in the following order. Retail > Volume:MAK > Volume:GVLK > OEM:NONSLP > OEM:DM | |
:: OEM keys are in last because they can't be used in edition change if "changepk /productkey" method is needed instead of "slmgr /ipk" | |
:: OEM keys are listed here because we don't have other keys for that edition | |
:changeeditiondata | |
set h= | |
for %%# in ( | |
44N%h%YX-TK%h%R9D-CCM2%h%D-V6%h%B8F-HQ%h%WWR__Volume:MAK_Enterprise | |
D6R%h%D9-D4%h%N8T-RT9Q%h%X-YW%h%6YT-FC%h%WWJ______Retail_Starter | |
3V6%h%Q6-NQ%h%XCX-V8YX%h%R-9Q%h%CYV-QP%h%FCT__Volume:MAK_EnterpriseN | |
3NF%h%XW-2T%h%27M-2BDW%h%6-4G%h%HRV-68%h%XRX______Retail_StarterN | |
VK7%h%JG-NP%h%HTM-C97J%h%M-9M%h%PGT-3V%h%66T______Retail_Professional | |
2B8%h%7N-8K%h%FHP-DKV6%h%R-Y2%h%C8J-PK%h%CKT______Retail_ProfessionalN | |
4CP%h%RK-NM%h%3K3-X6XX%h%Q-RX%h%X86-WX%h%CHW______Retail_CoreN | |
N24%h%34-X9%h%D7W-8PF6%h%X-8D%h%V9T-8T%h%YMD______Retail_CoreCountrySpecific | |
BT7%h%9Q-G7%h%N6G-PGBY%h%W-4Y%h%WX6-6F%h%4BT______Retail_CoreSingleLanguage | |
YTM%h%G3-N6%h%DKC-DKB7%h%7-7M%h%9GH-8H%h%VX7______Retail_Core | |
XKC%h%NC-J2%h%6Q9-KFHD%h%2-FK%h%THY-KD%h%72Y__OEM:NONSLP_PPIPro | |
YNM%h%GQ-8R%h%YV3-4PGQ%h%3-C8%h%XTP-7C%h%FBY______Retail_Education | |
84N%h%GF-MH%h%BT6-FXBX%h%8-QW%h%JK7-DR%h%R8H______Retail_EducationN | |
KCN%h%VH-YK%h%WX8-GJJB%h%9-H9%h%FDT-6F%h%7W2__Volume:MAK_EnterpriseS_VB | |
VBX%h%36-N7%h%DDY-M9H6%h%2-83%h%BMJ-CP%h%R42__Volume:MAK_EnterpriseS_RS5 | |
PN3%h%KR-JX%h%M7T-46HM%h%4-MC%h%QGK-7X%h%PJQ__Volume:MAK_EnterpriseS_RS1 | |
DVW%h%KN-3G%h%CMV-Q2XF%h%4-DD%h%PGM-VQ%h%WWY__Volume:MAK_EnterpriseS_TH | |
RQF%h%NW-9T%h%PM3-JQ73%h%T-QV%h%4VQ-DV%h%9PT__Volume:MAK_EnterpriseSN_VB | |
M33%h%WV-NH%h%Y3C-R7FP%h%M-BQ%h%GPT-23%h%9PG__Volume:MAK_EnterpriseSN_RS5 | |
2DB%h%W3-N2%h%PJG-MVHW%h%3-G7%h%TDK-9H%h%KR4__Volume:MAK_EnterpriseSN_RS1 | |
NTX%h%6B-BR%h%YC2-K678%h%6-F6%h%MVQ-M7%h%V2X__Volume:MAK_EnterpriseSN_TH | |
G3K%h%NM-CH%h%G6T-R36X%h%3-9Q%h%DG6-8M%h%8K9______Retail_ProfessionalSingleLanguage | |
HNG%h%CC-Y3%h%8KG-QVK8%h%D-WM%h%WRK-X8%h%6VK______Retail_ProfessionalCountrySpecific | |
DXG%h%7C-N3%h%6C4-C4HT%h%G-X4%h%T3X-2Y%h%V77______Retail_ProfessionalWorkstation | |
WYP%h%NQ-8C%h%467-V2W6%h%J-TX%h%4WX-WT%h%2RQ______Retail_ProfessionalWorkstationN | |
8PT%h%T6-RN%h%W4C-6V7J%h%2-C2%h%D3X-MH%h%BPB______Retail_ProfessionalEducation | |
GJT%h%YN-HD%h%MQY-FRR7%h%6-HV%h%GC7-QP%h%F8P______Retail_ProfessionalEducationN | |
C4N%h%TJ-CX%h%6Q2-VXDM%h%R-XV%h%KGM-F9%h%DJC__Volume:MAK_EnterpriseG | |
46P%h%N6-R9%h%BK9-CVHK%h%B-HW%h%Q9V-MB%h%JY8__Volume:MAK_EnterpriseGN | |
NJC%h%F7-PW%h%8QT-3324%h%D-68%h%8JX-2Y%h%V66______Retail_ServerRdsh | |
V3W%h%VW-N2%h%PV2-CGWC%h%3-34%h%QGF-VM%h%J2C______Retail_Cloud | |
NH9%h%J3-68%h%WK7-6FB9%h%3-4K%h%3DF-DJ%h%4F6______Retail_CloudN | |
2HN%h%6V-HG%h%TM8-6C97%h%C-RK%h%67V-JQ%h%PFD______Retail_CloudE | |
XQQ%h%YW-NF%h%FMW-XJPB%h%H-K8%h%732-CK%h%FFD______OEM:DM_IoTEnterprise | |
QPM%h%6N-7J%h%2WJ-P88H%h%H-P3%h%YRH-YY%h%74H__OEM:NONSLP_IoTEnterpriseS_VB | |
KBN%h%8V-HF%h%GQ4-MGXV%h%D-34%h%7P6-PD%h%QGT_Volume:GVLK_IoTEnterpriseS_NI | |
K9V%h%KN-3B%h%GWV-Y624%h%W-MC%h%RMQ-BH%h%DCD______Retail_CloudEditionN | |
KY7%h%PN-VR%h%6RX-83W6%h%Y-6D%h%DYQ-T6%h%R4W______Retail_CloudEdition | |
MPB%h%3G-XN%h%BR7-CC43%h%M-FG%h%64B-F9%h%GBK______Retail_IoTEnterpriseSK | |
) do ( | |
for /f "tokens=1-4 delims=_" %%A in ("%%#") do if /i %targetedition%==%%C ( | |
if not defined key ( | |
set 4th=%%D | |
if not defined 4th ( | |
set "key=%%A" & set "_chan=%%B" | |
) else ( | |
echo "%branch%" | find "%%D" 1>nul && (set "key=%%A" & set "_chan=%%B") | |
) | |
) | |
) | |
) | |
exit /b | |
::======================================================================================================================================== | |
:changeeditionserverdata | |
if exist "%SystemRoot%\Servicing\Packages\Microsoft-Windows-Server*CorEdition~*.mum" (set Cor=Cor) else (set Cor=) | |
:: Only RS3 and older version keys (GVLK/Generic Retail) are stored here, later ones are extracted from the system itself | |
set h= | |
for %%# in ( | |
WC2%h%BQ-8N%h%RM3-FDD%h%YY-2B%h%FGV-KHK%h%QY_RS1_ServerStandard%Cor% | |
CB7%h%KF-BW%h%N84-R7R%h%2Y-79%h%3K2-8XD%h%DG_RS1_ServerDatacenter%Cor% | |
JCK%h%RF-N3%h%7P4-C2D%h%82-9Y%h%XRT-4M6%h%3B_RS1_ServerSolution | |
QN4%h%C6-GB%h%JD2-FB4%h%22-GH%h%WJK-GJG%h%2R_RS1_ServerCloudStorage | |
VP3%h%4G-4N%h%PPG-79J%h%TQ-86%h%4T4-R3M%h%QX_RS1_ServerAzureCor | |
9JQ%h%NQ-V8%h%HQ6-PKB%h%8H-GG%h%HRY-R62%h%H6_RS1_ServerAzureNano | |
VN8%h%D3-PR%h%82H-DB6%h%BJ-J9%h%P4M-92F%h%6J_RS1_ServerStorageStandard | |
48T%h%QX-NV%h%K3R-D8Q%h%R3-GT%h%HHM-8FH%h%XC_RS1_ServerStorageWorkgroup | |
2HX%h%DN-KR%h%XHB-GPY%h%C7-YC%h%KFJ-7FV%h%DG_RS3_ServerDatacenterACor | |
PTX%h%N8-JF%h%HJM-4WC%h%78-MP%h%CBR-9W4%h%KR_RS3_ServerStandardACor | |
) do ( | |
for /f "tokens=1-3 delims=_" %%A in ("%%#") do if /i %targetedition%==%%C ( | |
echo "%branch%" | find /i "%%B" 1>nul && (set "key=%%A") | |
) | |
) | |
exit /b | |
::======================================================================================================================================== |