Forráskód Böngészése

stable

all issues ironed out
upgrade keeping files from Eval editions
earlier detect of setup ui exit
enhanced 11 AutoUnattend.xml
move bypass stuff from main readme
last squash I promise ;)
AveYo 3 éve
szülő
commit
79e59794f6

+ 2 - 0
.gitignore

@@ -1 +1,3 @@
 dev/
+$ISO$/
+*.iso

+ 358 - 258
MediaCreationTool.bat

@@ -2,10 +2,10 @@
 :Universal MCT wrapper script for all Windows 10/11 versions from 1507 to 21H2!
 :: Nothing but Microsoft-hosted source links and no third-party tools; script just configures an xml and starts MCT
 :: Ingenious support for business editions (Enterprise / VL) selecting language, x86, x64 or AiO inside the MCT GUI
-:: Changelog: 2021.12.22
-:: - improved auto.cmd handling of mismatched OS and target edition, obey 'def', 'auto' upgrades 7 to 10, not 11
-:: - skip 11 checks only via auto.cmd - ignore server label, please; local acc on 11 Home; output to CD or C:\ESD
-:: 11: 22000.318 / 21H2: 19044.1288 / 21H1: 19043.1348 / 20H2: 19042.1052 / 2004: 19041.572 / 1909: 18363.1139
+:: Changelog: 2022.03.20 stable
+:: - all issues ironed out; upgrade keeping files from Eval editions too; pickup $ISO$ dir content to add on media
+:: - DU in 11: auto installs 22000.556 atm; older skip_11_checks, without Server label; Home offline local account
+:: on upgrade: latest build, on offline install: 11 22000.318 / 21H2 19044.1288 / 21H1 19043.1348 / 20H2 19042.1052
 
 ::# uncomment to skip GUI dialog for MCT choice: 1507 to 2109 / 11 - or rename script: "21H2 MediaCreationTool.bat"
 rem set MCT=2110
@@ -29,9 +29,10 @@ rem set ARCH=x64
 rem set KEY=NPPR9-FWDCX-D2C8J-H872K-2YT43
 
 ::# uncomment to disable dynamic update for setup sources - or rename script: no_update 21H2 MediaCreationTool.bat"
-rem set /a NO_UPDATE=1 
+rem set /a NO_UPDATE=1
 
-::# uncomment to not add $OEM$ PID.txt EI.cfg auto.cmd unattend.xml - or rename script: "def MediaCreationTool.bat"
+::# uncomment to not add EI.cfg PID.txt auto.cmd $ISO$ dir content - or rename script:  "def MediaCreationTool.bat"
+::# this will create a default, untouched MCT media 
 rem set /a DEF=1
 
 ::# comment to not use recommended windows setup options that give the least amount of issues when doing upgrades
@@ -55,17 +56,17 @@ set PRESETS=^&Auto Upgrade,Auto ^&ISO,Auto ^&USB,^&Select,MCT ^&Defaults
 set /a dP=4
 
 :begin
-call :reg_query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentBuildNumber" OS_VERSION
-call :reg_query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" "DisplayVersion" OS_VID
-call :reg_query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" "EditionID" OS_EDITION
-call :reg_query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" "ProductName" OS_PRODUCT
+call :reg_query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentBuildNumber"     OS_VERSION
+call :reg_query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" "DisplayVersion"         OS_VID
+call :reg_query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" "EditionID"              OS_EDITION
+call :reg_query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" "ProductName"            OS_PRODUCT
 call :reg_query "HKU\S-1-5-18\Control Panel\Desktop\MuiCached" "MachinePreferredUILanguages" OS_LANGCODE
 for %%s in (%OS_LANGCODE%) do set "OS_LANGCODE=%%s"
 set "OS_ARCH=x64" & if "%PROCESSOR_ARCHITECTURE:~-2%" equ "86" if not defined PROCESSOR_ARCHITEW6432 set "OS_ARCH=x86"
 
 ::# parse MCT choice from script name or commandline - accepts both formats: 1909 or 19H2 etc.
-set V=1.1507 2.1511 3.1607 4.1703 5.1709 6.1803 7.1809 8.1903 8.19H1 9.1909 9.19H2 10.2004 10.20H1 11.2009 11.20H2 12.2104 12.21H1
-for %%V in (%V% 13.2109 13.21H2 14.2110 14.11) do for %%s in (%MCT% %~n0 %*) do if /i %%~xV equ .%%~s (set MCT=%%~nV&set VID=%%~s)
+for %%V in (1.1507 2.1511 3.1607 4.1703 5.1709 6.1803 7.1809 8.1903 8.19H1 9.1909 9.19H2 10.2004 10.20H1 11.2009 11.20H2 12.2104
+ 12.21H1 13.2109 13.21H2 14.2110 14.11) do for %%s in (%MCT% %~n0 %*) do if /i %%~xV equ .%%~s set "MCT=%%~nV" & set "VID=%%~s"
 if defined MCT if not defined VID set "MCT="
 
 ::# parse AUTO from script name or commandline - starts unattended upgrade / in-place repair / cross-edition
@@ -77,14 +78,14 @@ for %%s in (%~n0 %*) do if /i %%s equ iso set /a ISO=1
 if defined ISO set /a PRE=2 & if defined AUTO (set AUTO=)
 
 ::# parse EDITION from script name or commandline - accept one of the staged editions in MCT install.esd - see sources\product.ini
-set _=%EDITION% %~n0 %* & rem ::# also accepts the alternative names: Home, HomeN, Pro, ProN, Edu, EduN
+set _=%EDITION% %~n0 %*& rem ::# also accepts the alternative names: Home, HomeN, Pro, ProN, Edu, EduN
 for %%s in (%_:Home=Core% %_:Pro =Professional % %_:ProN=ProfessionalN% %_:Edu =Education % %_:EduN=EducationN%) do (
 for %%E in ( ProfessionalEducation ProfessionalEducationN ProfessionalWorkstation ProfessionalWorkstationN Cloud CloudN
  Core CoreN CoreSingleLanguage CoreCountrySpecific Professional ProfessionalN Education EducationN Enterprise EnterpriseN
 ) do if /i %%s equ %%E set "EDITION=%%E")
 
 ::# parse LANGCODE from script name or commandline - accepts any words starting with xy-
-for %%s in (%~n0 %*) do set ".=%%~s" & for /f %%C in ('cmd /q/v:on/r echo;!.:~2^,1!') do if "%%C" equ "-" set "LANGCODE=%%s"
+for %%s in (%~n0 %*) do set ".=%%~s" & for /f %%C in ('cmd /q /v:on /c echo;!.:~2^,1!') do if "%%C" equ "-" set "LANGCODE=%%s"
 
 ::# parse ARCH from script name or commandline - no, it does not accept "both"
 for %%s in (%~n0 %*) do for %%A in (x86 x64) do if /i %%s equ %%A set "ARCH=%%A"
@@ -98,12 +99,12 @@ if defined EDITION if "%PKEY1%" equ "%PKEY28%" (set "KEY=%PKEY%") else set "PKEY
 for %%s in (%~n0 %*) do if /i %%s equ no_update set "NO_UPDATE=1"
 if defined NO_UPDATE (set OPTIONS=%OPTIONS% /DynamicUpdate Disable) else (set OPTIONS=%OPTIONS% /DynamicUpdate Enable)
 
-::# parse DEF from script name or commandline - don't add $OEM$\, PID.txt, auto.cmd, Skip TPM (if applicable) to created media
-for %%s in (%~n0 %*) do if /i %%s equ def set "DEF=1"
-::# hint: setup can run a tweaking script before first logon, if present at $OEM$\$$\Setup\Scripts\ setupcomplete.cmd or OOBE.cmd
+::# parse DEF from script name or commandline - dont add $ISO$\, PID.txt, auto.cmd, Skip TPM (if applicable) to created media
+for %%s in (%~n0 %*) do if /i %%s equ def set "DEF=def"
+::# hint: setup can run a script before logon, if present at $ISO$\sources\$OEM$\$$\Setup\Scripts\setupcomplete.cmd or OOBE.cmd
 
-::# parse HIDE from script name or commandline - hide script windows while awaiting MCT processing (new default is to minimize)
-set hide=2& (for %%s in (%~n0 %*) do if /i %%s equ hide set hide=1)  
+::# parse HIDE from script name or commandline - hide script window while awaiting MCT processing (new default is to minimize)
+set /a hide=2 & for %%s in (%~n0 %*) do if /i %%s equ hide set /a hide=1
 
 ::# auto detected / selected media preset
 if defined EDITION (set MEDIA_EDITION=%EDITION%) else (set MEDIA_EDITION=%OS_EDITION%)
@@ -112,26 +113,26 @@ if defined ARCH (set MEDIA_ARCH=%ARCH%) else (set MEDIA_ARCH=%OS_ARCH%)
 if not defined VID (set VID=%OS_VID%)
 
 ::# edition fallback to ones that MCT supports
+(set MEDIA_EDITION=%MEDIA_EDITION:Eval=%)
 (set MEDIA_EDITION=%MEDIA_EDITION:Embedded=Enterprise%)
 (set MEDIA_EDITION=%MEDIA_EDITION:EnterpriseS=Enterprise%)
 (set MEDIA_EDITION=%MEDIA_EDITION:IoTEnterprise=Enterprise%)
 (set MEDIA_EDITION=%MEDIA_EDITION:IoTEnterpriseS=Enterprise%)
 
 ::# get previous GUI selection if self elevated and skip to choice
-for %%s in (%*) do for %%P in (1 2 3 4) do if %%~ns gtr 0 if %%~ns lss 15 if %%~xs. equ .%%P. set /a PRE=%%P& set /a MCT=%%~ns
-if defined PRE if defined MCT goto choice-%MCT%
+for %%s in (%*) do for %%P in (1 2 3 4) do if %%~ns gtr 0 if %%~ns lss 15 if %%~xs. equ .%%P. set /a PRE=%%P & set /a MCT=%%~ns
 
 ::# write auto media preset hint
 %<%:f0 " Detected Media "%>>% & if defined MCT %<%:5f " %VID% "%>>%
 %<%:6f " %MEDIA_LANGCODE% "%>>%  &  %<%:9f " %MEDIA_EDITION% "%>>%  &  %<%:2f " %MEDIA_ARCH% "%>%
-echo;   
+echo;
 %<%:1f "1  Auto Upgrade  : MCT gets detected media, script assists setupprep for upgrading "%>%
 %<%:1f "2    Auto ISO    : MCT gets detected media, script assists making ISO here | C:ESD "%>%
 %<%:1f "3    Auto USB    : MCT gets detected media, script assists making USB stick target "%>%
 %<%:1f "4     Select     : MCT gets selected Edition, Language, Arch onto specified target "%>%
 %<%:1f "5  MCT Defaults  : MCT runs unassisted, creating media without script modification "%>%
-echo;                                          
-%<%:17 "1-4 adds to media: PID.txt, EI.cfg, $OEM$ dir, auto.cmd for upgrade and tpm checks "%>%
+echo;
+%<%:17 "1-4 adds to media: PID.txt, EI.cfg, $ISO$ dir, auto.cmd for upgrade and tpm checks "%>%
 %<%:17 "can rename script: "%>>% & %<%:1f "def MediaCreationTool.bat"%>>% & %<%:17 " to always create unmodified MCT media "%>%
 
 ::# show more responsive MCT + PRE pseudo-menu dialog or separate choice dialog instances if either MCT or PRE are set
@@ -239,13 +240,13 @@ set "EXE=https://download.microsoft.com/download/C/F/9/CF9862F9-3D22-4811-99E7-6
 goto process ::# fastest for potato PCs (but with excruciantly slow windows update process)
 
 :choice- ;( something happened (broken environment/powershell?) and should cancel, but continue with defaults instead
-set MCT=%dv%& set PRE=%dP%& goto choice-%dV%
+set /a MCT=%dv% & set /a PRE=%dP% & goto choice-%dV%
 
 :choice-0
 %<%:0c " CANCELED "%>% & timeout /t 3 >nul & exit /b
 
-:latest unified console appearance under 7 - 11  
-@echo off& title MCT& set __COMPAT_LAYER=Installer& chcp 437 >nul& set set=& for %%s in (%*) do if /i %%s equ set set set=1 
+:latest unified console appearance under 7 - 11
+@echo off& title MCT& set __COMPAT_LAYER=Installer& chcp 437 >nul& set set=& for %%s in (%*) do if /i %%s equ set (set set=1)
 if not defined set set /a BackClr=0x1 & set /a TextClr=0xf & set /a Columns=32 & set /a Lines=120 & set /a Buff=9999
 if not defined set set /a SColors=BackClr*16+TextClr & set /a WSize=Columns*256*256+Lines & set /a BSize=Buff*256*256+Lines
 if not defined set for %%s in ("HKCU\Console\MCT") do (
@@ -261,25 +262,25 @@ if not defined set for %%s in ("HKCU\Console\MCT") do (
  reg add %%s /v QuickEdit      /d 0x0000 /t reg_dword /f & reg add %%s /v LineWrap /d 0 /t reg_dword /f
  reg add %%s /v LineSelection  /d 0x0001 /t reg_dword /f & reg add %%s /v CtrlKeyShortcutsDisabled /d 0 /t reg_dword /f
  reg add %%s /v WindowSize    /d %WSize% /t reg_dword /f & reg add %%s /v ScreenBufferSize /d %BSize% /t reg_dword /f
- reg add %%s /v FontSize   /d 0x00100008 /t reg_dword /f & reg add %%s /v FaceName /d "Consolas" /t reg_sz /f ) >nul 2>nul 
-::# set path, fix name (x) and reload from current directory
-pushd "%~dp0"& set "S=%SystemRoot%"& set "nx0=%~nx0"& call set "nx0=%%nx0:)=]%%"& call set "nx0=%%nx0:(=[%%"
+ reg add %%s /v FontSize   /d 0x00100008 /t reg_dword /f & reg add %%s /v FaceName /d "Consolas" /t reg_sz /f ) >nul 2>nul
+::# set path, fix name (x), always use C:\ESD as WORK directory to prevent issues and preserve current one as ROOT
+pushd "%~dp0" & set "S=%SystemRoot%" & set "nx0=%~nx0" & call set "nx0=%%nx0:)=]%%" & call set "nx0=%%nx0:(=[%%"
 set "PATH=%S%\Sysnative;%S%\Sysnative\windowspowershell\v1.0\;%S%\System32;%S%\System32\windowspowershell\v1.0\;%PATH%"
-set "ROOT=%CD%"& call set "dir=%%CD:%TEMP%=%%" &rem #:: fallback to C:\ESD if current directory is in TEMP (script run from zip)
-if "%dir%" neq "%CD%" for %%s in ("%SystemDrive%\ESD") do (mkdir %%s& attrib -R -S -H %%s& pushd %%s& set "ROOT=%%~s")>nul 2>nul
-(if "%~nx0" neq "%nx0%" copy /y "%~nx0" "%nx0%") & robocopy "%~dp0/" "%ROOT%/" "%nx0%" >nul
-if not defined set start "MCT" cmd /d/x/r call "%ROOT%\%nx0%" %* set& exit
+set "WORK=%SystemDrive%\ESD" & if not defined ROOT (set "ROOT=%CD%") else if not exist "%ROOT%\*.bat" set "ROOT=%CD%"
+mkdir "%WORK%" >nul 2>nul & attrib -R -S -H "%WORK%" >nul 2>nul & robocopy "%~dp0/" "%WORK%/" "%~nx0" >nul
+if "%~nx0" neq "%nx0%" copy /y "%WORK%\%~nx0" "%WORK%\%nx0%" >nul & del /f /q "%WORK%\%~nx0" >nul
+if not defined set start "MCT" cmd /d /x /c set "ROOT=%ROOT%" ^& call "%WORK%\%nx0%" %* set& exit /b
 ::# self-echo top 1-20 lines of script
-(<"%~f0" (set /p _=&for /l %%s in (1,1,20) do set _=& set /p _=& call echo;%%_%%))
+prompt $G & (<"%~f0" (set /p _=&for /l %%s in (1,1,20) do set _=& set /p _=& call echo;%%_%%)) 
 ::# lean xp+ color macros by AveYo:  %<%:af " hello "%>>%  &  %<%:cf " w\"or\"ld "%>%   for single \ / " use .%|%\  .%|%/  \"%|%\"
 for /f "delims=:" %%s in ('echo;prompt $h$s$h:^|cmd /d') do set "|=%%s"&set ">>=\..\c nul&set /p s=%%s%%s%%s%%s%%s%%s%%s<nul&popd"
-set "<=pushd "%public%"&2>nul findstr /c:\ /a" &set ">=%>>%&echo;" &set "|=%|:~0,1%" &set /p s=\<nul>"%public%\c"
+set "<=pushd "%appdata%"&2>nul findstr /c:\ /a" &set ">=%>>%&echo;" &set "|=%|:~0,1%" &set /p s=\<nul>"%appdata%\c"
 ::# (un)define main variables
 for %%s in (OPTIONS MCT XML CAB EXE VID PRE AUTO ISO EDITION KEY ARCH LANGCODE NO_UPDATE DEF AKEY) do set "%%s="
 for %%s in (latest_MCT.url) do if not exist %%s (echo;[InternetShortcut]&echo;URL=github.com/AveYo/MediaCreationTool.bat)>%%s
 goto Universal MCT
-::--------------------------------------------------------------------------------------------------------------------------------
 
+::--------------------------------------------------------------------------------------------------------------------------------
 :process
 if %PRE% equ 1 (set "PRESET=Auto Upgrade")
 if %PRE% equ 2 (set "PRESET=Auto ISO")
@@ -289,16 +290,17 @@ if %PRE% equ 5 (set "PRESET=MCT Defaults" & set EDITION=& set LANGCODE=& set ARC
 if %PRE% equ 5 (goto noelevate) else set set=%MCT%.%PRE%
 
 ::# self elevate if needed for the custom presets to monitor setup progress, passing arguments and last GUI choices
-fltmc>nul || (set _=start "MCT" cmd /d/x/r call "%~f0" %* %set%& powershell -nop -c start -verb runas cmd \"/d/x/r $env:_\"& exit)
-:noelevate 'MCT Defaults' does not need it, script just quits straightaway   
+fltmc>nul||(set A=/d /x /c set "ROOT=%ROOT%"^& start "MCT" "%~f0" %* %set%& powershell -nop -c start -verb runas cmd $env:A;&exit)
+:noelevate 'MCT Defaults' does not need it, script just quits straightaway
 
 ::# cleanup Downloads\MCT workfolder and stale mount files
-mkdir "%ROOT%\MCT" >nul 2>nul & attrib -R -S -H %ROOT% /D & pushd "%ROOT%\MCT"
-del /f /q products.* *.key EI.cfg PID.txt auto.cmd AutoUnattend.xml >nul 2>nul 
+mkdir "%WORK%\MCT" >nul 2>nul & attrib -R -S -H "%WORK%" /D & pushd "%WORK%\MCT"
+del /f /q products.* *.key EI.cfg PID.txt auto.cmd AutoUnattend.xml >nul 2>nul
 set /a latest=0 & if exist latest set /p latest=<latest
-echo;20220314>latest & if %latest% lss 20211116 del /f /q products*.* MediaCreationTool*.exe >nul 2>nul
+echo;20220320>latest & if %latest% lss 20211116 del /f /q products*.* MediaCreationTool*.exe >nul 2>nul
 
 ::# edition fallback to ones that MCT supports - after selection
+(set MEDIA_EDITION=%MEDIA_EDITION:Eval=%)
 (set MEDIA_EDITION=%MEDIA_EDITION:Embedded=Enterprise%)
 (set MEDIA_EDITION=%MEDIA_EDITION:IoTEnterprise=Enterprise%)
 (set MEDIA_EDITION=%MEDIA_EDITION:EnterpriseS=Enterprise%)
@@ -313,7 +315,7 @@ if %VER% neq 15063 (set MEDIA_EDITION=%MEDIA_EDITION:Cloud=Professional%)
 
 ::# generic key preset - only for staged editions in MCT install.esd - see sources\product.ini
 for %%s in (%MEDIA_EDITION%) do for %%K in (
-  V3WVW-N2PV2-CGWC3-34QGF-VMJ2C.Cloud                     NH9J3-68WK7-6FB93-4K3DF-DJ4F6.CloudN 
+  V3WVW-N2PV2-CGWC3-34QGF-VMJ2C.Cloud                     NH9J3-68WK7-6FB93-4K3DF-DJ4F6.CloudN
   YTMG3-N6DKC-DKB77-7M9GH-8HVX7.Core                      4CPRK-NM3K3-X6XXQ-RXX86-WXCHW.CoreN
   BT79Q-G7N6G-PGBYW-4YWX6-6F4BT.CoreSingleLanguage        N2434-X9D7W-8PF6X-8DV9T-8TYMD.CoreCountrySpecific
   VK7JG-NPHTM-C97JM-9MPGT-3V66T.Professional              2B87N-8KFHP-DKV6R-Y2C8J-PKCKT.ProfessionalN
@@ -324,12 +326,12 @@ for %%s in (%MEDIA_EDITION%) do for %%K in (
 ) do if /i %%~xK equ .%%s set MEDIA_EDITION=%%~xK& call set MEDIA_EDITION=%%MEDIA_EDITION:.=%%& set "MEDIA_KEY=%%~nK"
 
 ::# detected / selected media preset
-if defined EDITION (set EDITION=%MEDIA_EDITION%)  
+if defined EDITION (set EDITION=%MEDIA_EDITION%)
 if "%MEDIA_EDITION%" neq "%OS_EDITION%" (set REG_EDITION=%MEDIA_EDITION%) else set (REG_EDITION=)
 set "CONSUMER=%MEDIA_EDITION:Enterprise=%"
 if "%CONSUMER%" equ "%MEDIA_EDITION%" (set CFG=Consumer) else (set CFG=Business)
 if not defined EDITION (set UNSTAGED=1& set STAGED=) else (set UNSTAGED=& set STAGED=%MEDIA_EDITION%)
-if defined STAGED (set MEDIA_CFG=%STAGED%) else (set MEDIA_CFG=%CFG%)  
+if defined STAGED (set MEDIA_CFG=%STAGED%) else (set MEDIA_CFG=%CFG%)
 set MEDIA=& for %%s in (%LANGCODE%%EDITION%%ARCH%%KEY%) do (set MEDIA=%%s)
 if defined MEDIA for %%s in (%MEDIA_LANGCODE%) do (set LANGCODE=%%s)
 if defined MEDIA for %%s in (%MEDIA_EDITION%) do (set EDITION=%%s)
@@ -356,7 +358,7 @@ if defined CAB echo;%CAB% & call :DOWNLOAD "%CAB%" products%VID%.cab
 if exist products%VID%.xml copy /y products%VID%.xml products.xml >nul 2>nul
 if exist products%VID%.cab del /f /q products%VID%.xml >nul 2>nul
 if exist products%VID%.cab expand.exe -R products%VID%.cab -F:* . >nul 2>nul
-set "/hint=Check urls in browser | del MCT dir | use powershell v3.0+ | unblock powershell | enable BITS serv"
+set "/hint=Check urls in browser | del ESD dir | use powershell v3.0+ | unblock powershell | enable BITS serv"
 echo;& set err=& for %%s in (products.xml MediaCreationTool%VID%.exe) do if not exist %%s set err=1
 if defined err (%<%:4f " ERROR "%>>% & %<%:0f " %/hint% "%>%) else if not defined err %<%:0f " %PRESET% "%>%
 if defined err (del /f /q products%VID%.* MediaCreationTool%VID%.exe 2>nul & pause & exit /b1)
@@ -384,7 +386,7 @@ if "Select" equ "%PRESET%" (set MEDIA_SEL=)
 ::# separate options for MCT and auto.cmd
 set MOPTIONS=/Action CreateMedia %MEDIA_SEL% /Pkey Defer %OPTIONS% /SkipSummary /Eula Accept
 set AOPTIONS=/Auto Upgrade /MigChoice Upgrade %OPTIONS% /SkipSummary /Eula Accept
-set MAKE_OPTIONS=/SelfHost& for %%s in (%MOPTIONS%) do call set MAKE_OPTIONS=%%MAKE_OPTIONS%% %%s 
+set MAKE_OPTIONS=/SelfHost& for %%s in (%MOPTIONS%) do call set MAKE_OPTIONS=%%MAKE_OPTIONS%% %%s
 set AUTO_OPTIONS=/SelfHost& for %%s in (%AOPTIONS%) do call set AUTO_OPTIONS=%%AUTO_OPTIONS%% %%s
 
 ::# generate PID.txt to preset EDITION on boot media - MCT install.esd indexes only, ProWS/ProEdu only via auto.cmd
@@ -393,49 +395,50 @@ if not defined PKEY if "Enterprise" equ "%EDITION%" set "KEY=" &rem explicitly r
 if not defined KEY (del /f /q PID.txt 2>nul) else (echo;[PID]& echo;Value=%KEY%& echo;;Edition=%EDITION%)>PID.txt
 
 ::# generate EI.cfg for skipping key entry for generic 11 media
-if not defined KEY if %VER% geq 22000 (echo;[Channel]& echo;_Default)>EI.cfg    
+if not defined KEY if %VER% geq 22000 (echo;[Channel]& echo;_Default)>EI.cfg
 
-::# generate auto.cmd for upgrading without prompts - also copied to media so it can be re-run on demand 
-set "0=%~f0"& powershell -nop -c "iex ([io.file]::ReadAllText($env:0)-split'[:]generate_auto_cmd')[1];"
+::# generate auto.cmd for upgrading without prompts - also copied to media so it can be re-run on demand
+::# keep files and apps from Ultimate / PosReady / Embedded / LTSC / Enterprise Eval 
+set "0=%~f0"& powershell -nop -c "iex ([io.file]::ReadAllText($env:0) -split '[:]generate_auto_cmd')[1];"
 
 ::# generate AutoUnattend.xml for enabling offline local account on 11 Home editions
-::# gets placed inside boot.wim so that it does not affect setup under windows  
-set "0=%~f0"& powershell -nop -c "iex ([io.file]::ReadAllText($env:0)-split'[:]generate_AutoUnattend_xml')[1];"
+::# gets placed inside boot.wim so that it does not affect setup.exe under windows
+set "0=%~f0"& powershell -nop -c "iex ([io.file]::ReadAllText($env:0) -split '[:]generate_AutoUnattend_xml')[1];"
 
 ::# cleanup stale files
 dism /cleanup-wim >nul 2>nul
 
 ::# start script-assisted MCT via powershell (to monitor setup state and take necessary action)
-set "0=%~f0"& start "MCT" /wait /b powershell -nop -c "iex ([io.file]::ReadAllText($env:0)-split'[:]Assisted_MCT')[1];"
-if "Auto Upgrade" neq "%PRESET%" pause 
+set "0=%~f0" & powershell -nop -c "iex ([io.file]::ReadAllText($env:0) -split '[:]Assisted_MCT')[1];"
+if not defined DEF if %hide% neq 1 pause >nul
 
-::--------------------------------------------------------------------------------------------------------------------------------
-EXIT /BATCH DONE
-::--------------------------------------------------------------------------------------------------------------------------------
+EXIT
 
+::--------------------------------------------------------------------------------------------------------------------------------
 :Assisted_MCT
-#:: unreliable processing like pausing setuphost removed; enhanced output 
- $host.ui.rawui.windowtitle = "MCT $env:PRESET"; $ErrorActionPreference = 0
- $DRIVE = [environment]::SystemDirectory[0]; $WD = $DRIVE+':\ESD'; $WS = $DRIVE+':\$WINDOWS.~WS\Sources'; $DIR = $WS+'\Windows' 
- $ESD = $null; $USB = $null; $ISO = "$env:ROOT\$env:X $env:VIS $env:MEDIA_CFG $env:MEDIA_ARCH $env:MEDIA_LANGCODE.iso" 
- if ('Auto Upgrade' -eq $env:PRESET) {$ISO = [io.path]::GetTempPath() + "~temporary.iso"}
- del $ISO -force -ea 0 >''; if (test-path $ISO) {write-host ";( $ISO read-only or in use!`n" -fore 0xc; sleep 5; return}
- cd -Lit("$env:ROOT\MCT")
+#:: unreliable processing like pausing setuphost removed; enhanced output; automation fixes; iso output path kung-fu
+ $host.ui.rawui.windowtitle = "$env:PRESET $env:X $env:DEF"; $ErrorActionPreference = 0
+ [io.path]::GetTempPath(),$env:TEMP,$env:TMP |% { if ($env:ROOT -like "*$_*") {$env:ROOT=$env:WORK} } # was run from zip?
+ $DRIVE = [environment]::SystemDirectory[0]; $WD = $DRIVE+':\ESD'; $WS = $DRIVE+':\$WINDOWS.~WS\Sources'; $DIR = $WS+'\Windows'
+ $ESD = $null; $USB = $null; $ISO = "$env:ROOT\$env:X $env:VIS $env:MEDIA_CFG $env:MEDIA_ARCH $env:MEDIA_LANGCODE.iso"
+ if ('Auto Upgrade' -eq $env:PRESET) {$ISO = [io.path]::GetTempPath() + "~temporary.iso"}; del $ISO -force -ea 0 >$null
+ if (test-path $ISO) {write-host " ERROR! " -fore Red -nonew; write-host "$ISO is read-only or in use`r`n"; sleep 5; return}
+ cd -Lit("$env:WORK\MCT")
 
 #:: workaround for version 1703 and earlier not having media selection switches
  if ($env:VER -le 15063 -and $null -ne $env:REG_EDITION) {
    $K = '"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"'; $E = $env:REG_EDITION
-   start -nonew cmd "/d/x/r (reg add $K /v EditionID /d $E /reg:32 /f & reg delete $K /v ProductName /reg:32 /f) >nul 2>nul"
-   start -nonew cmd "/d/x/r (reg add $K /v EditionID /d $E /reg:64 /f & reg delete $K /v ProductName /reg:64 /f) >nul 2>nul"
+   cmd /d /x /c "(reg add $K /v EditionID /d $E /reg:32 /f & reg delete $K /v ProductName /reg:32 /f) >nul 2>nul"
+   cmd /d /x /c "(reg add $K /v EditionID /d $E /reg:64 /f & reg delete $K /v ProductName /reg:64 /f) >nul 2>nul"
  }
 
 #:: setup file watcher to minimally track progress
  function Watcher {
-   $A = $args; $Exe = $A[0]; $File = $A[1]; $Dir = $A[2]; $Subdirs = @($false,$true)[$A[3] -eq 'all'] 
-   $P = mkdir $Dir -force -ea 0; if (!(test-path $P)) {return 1}; $W = new-object IO.FileSystemWatcher; $W.Path = $P.FullName
+   $A = $args; $Exe = $A[0]; $File = $A[1]; $Folder = $A[2]; $Subdirs = @($false,$true)[$A[3] -eq 'all']
+   $P = mkdir $Folder -force -ea 0; if (!(test-path $P)) {return 1}; $W = new-object IO.FileSystemWatcher; $W.Path = $P.FullName
    $W.Filter = $File; $W.IncludeSubdirectories = $Subdirs; $W.NotifyFilter = 125; $W.EnableRaisingEvents = $true; $ret = 1
    while ($true) {
-     try { $get = $W.WaitForChanged(15, 15000) } catch { mkdir $Dir -ea 0 >''; continue }
+     try { $get = $W.WaitForChanged(15, 15000) } catch { mkdir $Folder -ea 0 >$null; continue }
      if (-not $get.TimedOut) { write-host -fore Gray $get.ChangeType,$get.Name; $ret = 0;break} else {if ($Exe.HasExited) {break}}
    } ; $W.Dispose(); return $ret
  }
@@ -446,182 +449,230 @@ EXIT /BATCH DONE
  $re = $an |% { [Reflection.Assembly]::LoadWithPartialName("'$_") } ; try { & $ca } catch { & $ca }
  $cp = [Windows.Automation.AutomationElement]::ClassNameProperty
  $bt = "Button","ComboBox","Edit" |% {new-object Windows.Automation.PropertyCondition($cp, $_)}
- new-item -path function: -name "Enter" -value { $app = get-process "SetupHost" -ea 0; if ($null -ne $app)
- { [Microsoft.VisualBasic.Interaction]::AppActivate($app.Id)} ; [Windows.Forms.SendKeys]::SendWait("{ENTER}") } >'' 
+ $null = new-item -path function: -name "Enter" -value { $app = get-process "SetupHost" -ea 0
+ if ($null -ne $app) {[Microsoft.VisualBasic.Interaction]::AppActivate($app.Id)}; [Windows.Forms.SendKeys]::SendWait("{ENTER}") }
  $id = 0; if ('Auto USB' -ne $env:PRESET) {$id = 1}
  $sw = "ShowWindowAsync"; $dm = [AppDomain]::CurrentDomain."DefineDynami`cAssembly"(1,1)."DefineDynami`cModule"(1)
- $dt = $dm."Defin`eType"("AveYo",1179913,[ValueType]); $ptr = (get-process -pid $PID).MainWindowHandle.gettype() 
- $dt."DefinePInvok`eMethod"($sw,"user`32",8214,1,[void],@($ptr,[int]),1,4) >''; $nt = $dt."Creat`eType"()
- new-item -path function: -name "ShowWindow" -value {$nt."G`etMethod"($sw).invoke(0,@($args[0],$args[1]))} >''
+ $dt = $dm."Defin`eType"("AveYo",1179913,[ValueType]); $ptr = (get-process -pid $PID).MainWindowHandle.gettype()
+ $dt."DefinePInvok`eMethod"($sw,"user`32",8214,1,[void],@($ptr,[int]),1,4) >$null; $nt = $dt."Creat`eType"()
+ new-item -path function: -name "ShowWindow" -value {$nt."G`etMethod"($sw).invoke(0,@($args[0],$args[1]))} >$null
 
 #:: start monitoring
  :mct while ($true) {
   #:: launch MCT with /Selfhost /Action CreateMedia options and wait for main window
    $set = get-process SetupHost -ea 0; if ($set) {$set.Kill()}
-   $mct = start -passthru "MediaCreationTool${env:VID}.exe" $env:MAKE_OPTIONS; if ($null -eq $mct) {break} 
+   $mct = start -passthru "$env:WORK\MCT\MediaCreationTool${env:VID}.exe" $env:MAKE_OPTIONS; if ($null -eq $mct) {break :mct}
    while ($null -eq (get-process SetupHost -ea 0)) {if ($mct.HasExited) {break :mct}; sleep -m 200 }
-   $set = get-process SetupHost -ea 0; if ($null -eq $set) {break}
+   $set = get-process SetupHost -ea 0; if ($null -eq $set) {break :mct}
    while ($set.MainWindowHandle -eq 0) { if ($mct.HasExited) {break :mct}; $set.Refresh(); sleep -m 200 }
 
   #:: using automation to click gui buttons directly due to UpgradeNow and CreateUpgradeMedia actions no longer working in 11 MCT
    if ('Select' -ne $env:PRESET) { try {
-     $win = [Windows.Automation.AutomationElement]::FromHandle($set.MainWindowHandle); $nr = $win.FindAll(5, $bt[0]).Count 
+     $win = [Windows.Automation.AutomationElement]::FromHandle($set.MainWindowHandle); $nr = $win.FindAll(5, $bt[0]).Count
      if ($env:VER -le 15063) {while ($win.FindAll(5,$bt[1]).Count -lt 3) {if ($mct.HasExited) {break :mct}; sleep -m 200}; Enter}
-     while ($win.FindAll(5,$bt[0]).Count -le $nr) {if ($mct.HasExited) {break :mct}; sleep -m 200}; $all = $win.FindAll(5,$bt[0]) 
+     while ($win.FindAll(5,$bt[0]).Count -le $nr) {if ($mct.HasExited) {break :mct}; sleep -m 200}; $all = $win.FindAll(5,$bt[0])
      $all[$id].GetCurrentPattern([Windows.Automation.SelectionItemPattern]::Pattern).Select();$all[$all.Count-1].SetFocus(); Enter
      if ('Auto USB' -ne $env:PRESET) {
        while ($win.FindAll(5,$bt[2]).Count -le 0) {if ($mct.HasExited) {break :mct};sleep -m 50}; $val = $win.FindAll(5,$bt[2])[0]
-       $val.GetCurrentPattern([Windows.Automation.ValuePattern]::Pattern).SetValue($ISO); $all = $win.FindAll(5, $bt[0])
-       ($all |? {$_.Current.AutomationId -eq 1}).SetFocus(); Enter # sendkeys Enter - due to unreliable InvokePattern click()
+       # using sendkeys Enter due to unreliable InvokePattern click(); extra sendwait(" ") + flush() due to new edit control issue
+       [Windows.Forms.SendKeys]::SendWait(" "); $val.GetCurrentPattern([Windows.Automation.ValuePattern]::Pattern).SetValue($ISO)
+       [Windows.Forms.SendKeys]::Flush(); $b = $win.FindAll(5, $bt[0]); ($b |? {$_.Current.AutomationId -eq 1}).SetFocus(); Enter
      }
    } catch {} }
-  
-  #:: if DEF parameter used, quit without adding $OEM$, pid.txt, auto.cmd (includes 11 Setup override) to media
-   if ($null -ne $env:DEF -and 'Auto Upgrade' -ne $env:PRESET) {break :mct} 
+
+  #:: if DEF parameter used, quit without adding $ISO$, pid.txt, auto.cmd (includes 11 Setup override) to media
+   if ($null -ne $env:DEF -and 'Auto Upgrade' -ne $env:PRESET) {break :mct}
 
   #:: get target $ISO or $USB from setup state file
    $ready = $false; $task = "PreDownload"; $action = "GetWebSetupUserInput"
-   while (-not $ready) { 
-     [xml]$xml = get-content "$WS\Panther\windlp.state.xml" 
+   while (-not $ready) {
+     [xml]$xml = get-content "$WS\Panther\windlp.state.xml"
      foreach ($t in $xml.WINDLP.TASK) { if ($t.Name -eq $task) { foreach ($a in $t.ACTION) { if ($a.ActionName -eq $action) {
        if ($null -ne $a.DownloadUrlX86) {$ESD = $a.DownloadUrlX86}
        if ($null -ne $a.DownloadUrlX64) {$ESD = $a.DownloadUrlX64}
        if ($null -ne $a.TargetISO) {$ISO = $a.TargetISO; $ready = $true}
        $u = $a.TargetUsbDrive; if ($null -ne $u -and $u -gt 0) {$USB = [char][Convert]::ToInt32($u, 16) + ":"; $ready = $true}
      }}}} ; if ($mct.HasExited) {break :mct}; sleep -m 1000
-   }                                         
+   }
+ 
+   if ($mct.HasExited) {break :mct} # earlier detect of setup ui exit 
    if ('Auto Upgrade' -ne $env:PRESET -and $null -eq $USB) {write-host -fore Gray "Prepare", $ISO}
    if ('Auto Upgrade' -ne $env:PRESET -and $null -ne $USB) {write-host -fore Gray "Prepare", $USB}
    if ('Auto Upgrade' -eq $env:PRESET) {write-host -fore Gray "Prepare", $DIR}
-   $label = "${env:X}_${env:VIS}" + ($ESD -split '(?=_client)')[1] 
+   $label = "${env:X}_${env:VIS}" + ($ESD -split '(?=_client)')[1]
+   $label = $label -replace '_clientconsumer','' -replace '_clientbusiness','' -replace 'fre_','_' -replace '.esd',''
    write-host -fore Gray "FromESD", $label; sleep 10; powershell -win $env:hide -nop -c ";"
-
-  #:: watch setup files progress from the sideline (MCT has authoring control)
-   write-host -fore Yellow "Started ESD download"; Watcher $mct "*.esd"  $WD all >''; if ($mct.HasExited) {break}
-   write-host -fore Yellow "Started media create"; Watcher $mct "*.wim"  $WS all >''; if ($mct.HasExited) {break}
-   #write-host -fore Yellow "Started media layout"; Watcher $mct "ws.dat" $WS all >''; if ($mct.HasExited) {break}
-                            
-  #:: add to media $OEM$, EI.cfg, PID.txt, auto.cmd (includes 11 Setup override) - disable via DEF arg
-   pushd -lit "$env:ROOT"; foreach ($P in "$DIR\x86\sources","$DIR\x64\sources","$DIR\sources") {
-     if (($null -ne $env:DEF) -or !(test-path "$P\setupprep.exe")) {continue}
-     if ($ESD -like '*_vol_*') {del "MCT\EI.cfg" -force -ea 0 >''}
-     $f1 = '$OEM$'; if (test-path -lit $f1) {xcopy /CYBERHIQ $f1 "$P\$f1" >''; write-host -fore Gray AddFile $f1}
-     $f2 = "MCT\EI.cfg"; if (test-path $f2) {copy -path $f2 -dest $P -force >''; write-host -fore Gray AddFile $f2}
-     $f3 = "MCT\PID.txt"; if (test-path $f3) {copy -path $f3 -dest $P -force >''; write-host -fore Gray AddFile $f3}
-     $f4 = "MCT\auto.cmd"; if (test-path $f4) {copy -path $f4 -dest $DIR -force >''; write-host -fore Gray AddFile $f4}
-   } ; popd
+   if ($mct.HasExited) {break :mct} # earlier detect of setup ui exit
    
-  #:: watch media layout progress
-   $ready = $false; $task = "MediaCreate"; $action = "IsoLayout"; if ($null -ne $USB) {$action = "UsbLayout"}
-   while (-not $ready) { 
+  #:: watch setup files progress from the sideline (MCT has authoring control)
+   write-host -fore Yellow "Started ESD download"; Watcher $mct "*.esd" $WD all >$null; if ($mct.HasExited) {break :mct}
+   write-host -fore Yellow "Started media create"; Watcher $mct "*.wim"  $WS all >$null; if ($mct.HasExited) {break :mct}
+   #write-host -fore Yellow "Started media layout"; Watcher $mct "ws.dat" $WS all >$null; if ($mct.HasExited) {break :mct}
+
+  #:: add to media EI.cfg, PID.txt, auto.cmd, $ISO$ dir - disable via DEF arg
+  #:: [issue #91] pick up $ISO$ content and add it to the root of the created media - place your $OEM$ into $ISO$\sources\$OEM$
+   if ($null -eq $env:DEF) {
+     pushd -lit "$env:ROOT"
+     $f1 = '$ISO$'; if (test-path $f1) {xcopy /CYBERHIQ $f1 "$DIR" >$null; write-host -fore Gray "AddDirs", $f1} ; popd
+     pushd -lit "$env:WORK"
+     if (-not (test-path "$DIR\auto.cmd")) {
+       $f2 = "MCT\auto.cmd"; if (test-path $f2) {copy -path $f2 -dest $DIR -force >$null; write-host -fore Gray "AddFile", $f2}
+     }
+     foreach ($P in "$DIR\x86\sources","$DIR\x64\sources","$DIR\sources") {
+       if (!(test-path "$P\setupprep.exe")) {continue}
+       if (-not (test-path "$DIR\EI.cfg") -and ($ESD -like '*_ret_*')) {
+         $f3 = "MCT\EI.cfg"; if (test-path $f3) {copy -path $f3 -dest $P -force >$null; write-host -fore Gray "AddFile", $f3}
+       }
+       if (-not (test-path "$DIR\PID.txt")) {
+         $f4 = "MCT\PID.txt"; if (test-path $f4) {copy -path $f4 -dest $P -force >$null; write-host -fore Gray "AddFile", $f4}
+       }
+     } ; popd
+   }
+
+  #:: watch media layout progress (with status)
+   write-host -fore Gray "Convert install.esd"
+   $ready = $false; $task = "MediaCreate"; $action = "Layout"
+   while (-not $ready) {
      [xml]$xml = get-content "$WS\Panther\windlp.state.xml"
      foreach ($t in $xml.WINDLP.TASK) { if ($t.Name -eq $task) { foreach ($a in $t.ACTION) { if ($a.ActionName -eq $action) {
-       if ($null -ne $a.ProgressCurrent -and 0 -ne $a.ProgressCurrent) {$ready = $true}
+       $total = $a.ProgressTotal; $current = $a.ProgressCurrent
+       if ($null -ne $total -and 0 -ne $total -and $total -eq $current) {$ready = $true}
+       if ($null -ne $current -and 0 -ne $current) {$done = [Convert]::ToInt64($current, 16)} else {$done = 0}
+       write-host -nonew -fore Gray "`r${done}% "
      }}}} ; if ($mct.HasExited) {break :mct}; sleep -m 10000
    }
-   write-host -fore Yellow "Started", $action
-   $set = get-process SetupHost -ea 0; $global:handle = $set.MainWindowHandle; ShowWindow $handle 0
-   if (2 -eq $env:hide) {powershell -win 0 -nop -c ";"}
+   $action = "IsoLayout"; if ($null -ne $USB) {$action = "UsbLayout"}
+   write-host -fore Yellow "`r`nStarted $action"
 
-  #:: watch usb layout progress if target is $USB
+  #:: watch usb layout progress (with status) if target is $USB
    if ($null -ne $USB) {
-     $ready = $false; $task = "MediaCreate"; $action = "UsbLayout"
-     while (-not $ready) { 
+     $ready = $false; $task = "MediaCreate"; $action = "UsbLayout"; $size = 0; $almost = 0; $foreground = 0
+     while (-not $ready) {
+       sleep -m 5000; if ($mct.HasExited) {break :mct}
        [xml]$xml = get-content "$WS\Panther\windlp.state.xml"
        foreach ($t in $xml.WINDLP.TASK) { if ($t.Name -eq $task) { foreach ($a in $t.ACTION) { if ($a.ActionName -eq $action) {
          $total = $a.ProgressTotal; $current = $a.ProgressCurrent
-         if ($null -ne $total -and 0 -ne $total -and $total -eq $current) {$ready = $true} 
-       }}}} ; if ($mct.HasExited) {break :mct}; sleep -m 5000
+         if ($null -ne $total -and 0 -ne $total -and $total -eq $current) {$ready = $true}
+        #:: hide setup ui and show script window in foreground (to prevent ui stalling / working dir cleanup when done)
+         if ($size -eq 0) {$size = [Math]::Ceiling([Convert]::ToInt64($total, 16)/1048576); $almost = $size * 0.8}
+         $done = [Math]::Ceiling([Convert]::ToInt64($current, 16)/1048576)
+         if ($foreground -eq 0 -and $done -gt $almost) {
+           $set = get-process SetupHost -ea 0; $SetupHost = $set.MainWindowHandle; powershell -win 0 -nop -c ";"
+           ShowWindow $SetupHost 0; ShowWindow (get-process -Id $PID).MainWindowHandle 1; $foreground = 1
+         }
+         write-host -nonew -fore Gray "`r${size} MB  written: ${done} MB "
+       }}}}
      }
-     write-host -fore Gray "Created", $action
+     write-host -fore Gray "`r`nCreated $action"
    }
-  
+
   #:: kill MCT process before temporary iso finish
    if ($env:VER -ge 22000 -or 'Auto Upgrade' -eq $env:PRESET) {
-     $mct.Kill(); $s = get-process SetupPrep,SetupHost -ea 0; if ($s) { foreach ($setup in $s) {$setup.Kill()} } 
-     sleep 3; start -nonew cmd '/d/x/r dism /cleanup-wim >nul 2>nul'; del $ISO -force -ea 0 >''
-   } 
+     $mct.Kill(); $s = get-process SetupPrep,SetupHost -ea 0; if ($s) { foreach ($setup in $s) {$setup.Kill()} }
+     powershell -win 0 -nop -c ";"; ShowWindow (get-process -Id $PID).MainWindowHandle 1
+     sleep 3; cmd /d /x /c "dism /cleanup-wim >nul 2>nul"; del $ISO -force -ea 0 >$null
+   }
 
-  #:: end monitoring 
+  #:: end monitoring
    break :mct
  }
-
 #:: undo workaround for version 1703 and earlier not having media selection switches
  if ($env:VER -le 15063 -and $null -ne $env:REG_EDITION) {
    $K = '"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"'; $E = $env:OS_EDITION; $P = $env:OS_PRODUCT
-   start -nonew cmd "/d/x/r (reg add $K /v EditionID /d $E /reg:32 /f & reg add $K /v ProductName /d $P /reg:32 /f) >nul 2>nul"
-   start -nonew cmd "/d/x/r (reg add $K /v EditionID /d $E /reg:64 /f & reg add $K /v ProductName /d $P /reg:64 /f) >nul 2>nul"
+   cmd /d /x /c "(reg add $K /v EditionID /d $E /reg:32 /f & reg add $K /v ProductName /d $P /reg:32 /f) >nul 2>nul"
+   cmd /d /x /c "(reg add $K /v EditionID /d $E /reg:64 /f & reg add $K /v ProductName /d $P /reg:64 /f) >nul 2>nul"
  }
- 
-#:: Auto Upgrade preset starts auto.cmd from $DIR = C:\$WINDOWS.~WS\Sources\Windows 
- if ('Auto Upgrade' -eq $env:PRESET) {
-   cd -Lit("$env:ROOT\MCT"); start -nonew cmd "/d/x/r call auto.cmd $DIR"
-   write-host "`r`n UPGRADING $env:EDITION_SWITCH... `r`n"; sleep 7; return
+
+#:: if terminated unexpectedly or DEF used for default, untouched media:
+ if (-not (test-path "$DIR\sources\ws.dat")) {
+   if ((get-process SetupHost -ea 0) -and $null -ne $env:DEF) {return}
+   powershell -win 0 -nop -c ";"; ShowWindow (get-process -Id $PID).MainWindowHandle 1
+   pushd -lit "$env:WORK"; cmd /d /x /c "pushd c:\ & rmdir /s /q ""$DIR"" >nul 2>nul & del /f /q ""$WS\*.*"" >nul 2>nul"
+   write-host " ERROR! " -fore Red -nonew; write-host "setup terminated unexpectedly`r`n"; sleep 7; return
  } 
 
+#:: back to classic 0-byte skip 11 upgrade checks as it still works in release - and people keep nagging about Server label
+ if ($env:VER -ge 22000) {
+   cmd /d /x /c "cd.>""$DIR\sources\appraiserres.dll"""
+ }
+
+#:: Auto Upgrade preset starts auto.cmd from $DIR = C:\$WINDOWS.~WS\Sources\Windows
+ if ('Auto Upgrade' -eq $env:PRESET) {
+   cd -Lit("$env:WORK\MCT"); cmd /d /x /c "call ""$env:WORK\MCT\auto.cmd"" ""$DIR"""; sleep 7; return
+ }
+
 #:: skip windows 11 upgrade checks - for running setup from boot media
  if ($env:VER -ge 22000 -and (test-path "$DIR\sources\boot.wim")) {
-   write-host -fore Yellow "Disable boot.wim 11 setup checks"
-   rmdir "$WD\MOUNT" -re -force -ea 0; mkdir "$WD\MOUNT" -force -ea 0 >''; $winsetup = "$WD\MOUNT\sources\winsetup.dll"
-   dism.exe /mount-wim /wimfile:"$DIR\sources\boot.wim" /index:2 /mountdir:"$WD\MOUNT"; write-host 
-   try {takeown.exe /f $winsetup /a >''; icacls.exe $winsetup /grant *S-1-5-32-544:f; attrib -R -S $winsetup; $patch = '/commit'
-     [io.file]::OpenWrite($winsetup).close()} catch {$patch = '/discard'}
+   write-host -fore Gray "Disable boot.wim 11 setup checks - can use def for default MCT media instead"
+   rmdir "$WD\MOUNT" -re -force -ea 0; mkdir "$WD\MOUNT" -force -ea 0 >$null; $winsetup = "$WD\MOUNT\sources\winsetup.dll"
+   dism.exe /mount-wim /wimfile:"$DIR\sources\boot.wim" /index:2 /mountdir:"$WD\MOUNT"; write-host
+   if (-not (test-path "$DIR\AutoUnattend.xml")) {
+     $f5 = "$env:WORK\MCT\AutoUnattend.xml" 
+     if (test-path $f5) {write-host importing file: $f5; copy -path $f5 -dest "$WD\MOUNT" -force >$null}
+   }
+   try { takeown.exe /f $winsetup /a >$null; icacls.exe $winsetup /grant *S-1-5-32-544:f; attrib -R -S $winsetup
+     $patch = '/commit'; [io.file]::OpenWrite($winsetup).close() } catch {$patch = '/discard'}
    if ($patch -eq '/commit') { #:: an original setup override by AveYo to use when registry overrides fail (VirtualBox 5.x)
-     $b = [io.file]::ReadAllBytes($winsetup); $h = [BitConverter]::ToString($b)-replace'-' 
-     $s = [BitConverter]::ToString([Text.Encoding]::Unicode.GetBytes('Module_Init_HWRequirements'))-replace'-'
+     $b = [io.file]::ReadAllBytes($winsetup); $h = [BitConverter]::ToString($b) -replace '-'
+     $s = [BitConverter]::ToString([Text.Encoding]::Unicode.GetBytes('Module_Init_HWRequirements')) -replace '-'
      $i = ($h.IndexOf($s)/2); $r = [Text.Encoding]::Unicode.GetBytes('Module_Init_GatherDiskInfo'); $l = $r.Length
      if ($i -gt 1) {for ($k=0;$k -lt $l;$k++) {$b[$i+$k] = $r[$k]}; [io.file]::WriteAllBytes($winsetup,$b)}; [GC]::Collect()
-   }  
-   $f5 = "$env:ROOT\MCT\AutoUnattend.xml"; if (test-path $f5) {copy -path $f5 -dest "$WD\MOUNT" -force >''}   
-   dism.exe /unmount-wim /mountdir:"$WD\MOUNT" $patch; rmdir "$WD\MOUNT" -re -force -ea 0; write-host
+   }
+   dism.exe /unmount-wim /mountdir:"$WD\MOUNT" $patch; rmdir "$WD\MOUNT" -re -force -ea 0
+
+  #:: create media
    if ($null -ne $USB) {
-     write-host -fore Yellow "MakeUSB $USB"
+     write-host -fore Yellow "Refresh USB $USB"
      #:: if target is $USB, refresh boot.wim from sources
      replace "$DIR\sources\boot.wim" "$USB\sources" /r /u
    } else {
-     write-host -fore Yellow "MakeISO"
-     #:: if target is $ISO, load snippet then call DIR2ISO DIR ISO LABEL
-     iex ([io.file]::ReadAllText($env:0)-split '#\:DIR2ISO\:' ,3)[1]
-     DIR2ISO $DIR $ISO $label
+     write-host -fore Yellow "Refresh ISO"
+     #:: if target is $ISO, load then call MakeISO snippet (formerly named DIR2ISO)
+     iex ([io.file]::ReadAllText($env:0) -split '#\:MakeISO\:' ,3)[1]
+     MakeISO $DIR $ISO $label
    }
-  #:: cleanup 
-   pushd -lit "$env:ROOT"; start -wait "$DIR\sources\setupprep.exe" "/cleanup"
-   start -nonew cmd "/d/x/c rmdir /s /q ""$DIR"" & del /f /q ""$WS\*.*""" >'' 
+  #:: cleanup
+   pushd -lit "$env:WORK"; try {start -wait "$DIR\sources\setupprep1.exe" "/cleanup"} catch {}
+   cmd /d /x /c "pushd c:\ & rmdir /s /q ""$DIR"" >nul 2>nul & del /f /q ""$WS\*.*"" >nul 2>nul"
  }
 
- write-host "`r`nDONE`r`n"; sleep 7; return
+ write-host -fore Green "`r`n DONE "; write-host Press any key to exit . . .; sleep 7; return 
 #:: done #:Assisted_MCT
-::--------------------------------------------------------------------------------------------------------------------------------
 
+::--------------------------------------------------------------------------------------------------------------------------------
 :generate_auto_cmd $text = @"
-@echo off& set root=%1& set title= Auto Upgrade with edition switch support `r`nset "EDITION_SWITCH=$env:EDITION_SWITCH"
-set "SKIP_11_SETUP_CHECKS=$((0,1)[$null -eq $env:DEF])"`r`nset OPTIONS=$env:AUTO_OPTIONS`r`n`r`n
+@echo off& title Auto Upgrade  ||  supports Ultimate / PosReady / Embedded / LTSC / Enterprise Eval
+set "EDITION_SWITCH=$env:EDITION_SWITCH"
+set "SKIP_11_SETUP_CHECKS=$((0,1)[$null -eq $env:DEF])"
+set OPTIONS=$env:AUTO_OPTIONS`r`n`r`n
 "@ + @'
-pushd "%~dp0"& if defined root pushd %root% 
+pushd "%~dp0" & for %%w in (%1) do pushd %%w
 for %%i in ("x86\" "x64\" "") do if exist "%%~isources\setupprep.exe" set "dir=%%~i"
-pushd "%dir%sources" || (echo "%dir%sources" & timeout /t 5 & exit /b)
-setlocal EnableDelayedExpansion
+pushd "%dir%sources" || (echo "%dir%sources" not found! script should be run from windows setup media & timeout /t 5 & exit /b)
+
+::# start sources\setup if under winpe (when booted from media) [Shift] + [F10]: c:\auto or d:\auto or e:\auto etc.
+reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\WinPE">nul 2>nul && (
+ for %%s in (sCPU sRAM sSecureBoot sStorage sTPM) do reg add HKLM\SYSTEM\Setup\LabConfig /f /v Bypas%%sCheck /d 1 /t reg_dword
+ start "WinPE" sources\setup.exe & exit /b 
+) 
 
-::# start sources\setup if under winpe (when booted from media)
-reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\WinPE">nul 2>nul && (start "WinPE" sources\setup.exe &exit /b)
+::# init variables
+setlocal EnableDelayedExpansion
+set "PATH=%SystemRoot%\System32;%SystemRoot%\System32\windowspowershell\v1.0\;%PATH%"
+set "PATH=%SystemRoot%\Sysnative;%SystemRoot%\Sysnative\windowspowershell\v1.0\;%PATH%"
 
 ::# elevate so that workarounds can be set under windows
-fltmc>nul || (set _="%~f0" %*& powershell -nop -c start -verb runas cmd \"/d/x/r call $env:_\"& exit /b)
+fltmc >nul || (set _="%~f0" %*& powershell -nop -c start -verb runas cmd \"/d /x /c call $env:_\"& exit /b)
 
 ::# undo any previous regedit edition rename (if upgrade was interrupted)
-set EI=& set PN=& set NT="HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"  
-for /f "tokens=2*" %%R in ('reg query %NT% /v EditionID_undo /reg:64 2^>nul') do set "EI=%%S"
-for /f "tokens=2*" %%R in ('reg query %NT% /v ProductName_undo /reg:64 2^>nul') do set "PN=%%S"
-for %%a in (32 64) do (
- if defined EI reg add %NT% /v EditionID /d "%EI%" /f /reg:%%a   & reg delete %NT% /v EditionID_undo /f /reg:%%a
- if defined PN reg add %NT% /v ProductName /d "%EI%" /f /reg:%%a & reg delete %NT% /v ProductName_undo /f /reg:%%a
+set "NT=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
+for %%v in (CompositionEditionID EditionID ProductName) do (
+ call :reg_query "%NT%" %%v_undo %%v
+ if defined %%v reg delete "%NT%" /v %%v_undo /f & for %%A in (32 64) do reg add "%NT%" /v %%v /d "!%%v!" /f /reg:%%A 
 ) >nul 2>nul
 
 ::# get current version
-set EditionID=& set ProductName=& set NT="HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"                       
-for /f "tokens=2*" %%R in ('reg query %NT% /v EditionID /reg:64 2^>nul') do set "EditionID=%%S"
-for /f "tokens=2*" %%R in ('reg query %NT% /v ProductName /reg:64 2^>nul') do set "ProductName=%%S"
-for /f "tokens=2*" %%R in ('reg query %NT% /v CurrentBuildNumber /reg:64 2^>nul') do set "CurrentBuild=%%S"
+for %%v in (CompositionEditionID EditionID ProductName CurrentBuildNumber) do call :reg_query "%NT%" %%v %%v
 for /f "tokens=2-3 delims=[." %%i in ('ver') do for %%s in (%%i) do set /a Version=%%s*10+%%j
 
 ::# WIM_INFO w_5=wim_5th b_5=build_5th p_5=patch_5th a_5=arch_5th l_5=lang_5th e_5=edi_5th d_5=desc_5th i_5=edi_5th i_Core=index
@@ -637,63 +688,82 @@ echo;---------------------------------------------------------------------------
 
 ::# get requested edition in EI.cfg or PID.txt or OPTIONS
 if exist product.ini for /f "tokens=1,2 delims==" %%O in (product.ini) do if not "%%P" equ "" (set pid_%%O=%%P& set pn_%%P=%%O)
-set EI=& set Name=& set nID=& set reg=& set "cfg_filter=EditionID Channel OEM Retail Volume _Default VL 0 1 ^$"
-if exist EI.cfg for /f "tokens=*" %%i in ('findstr /v /i /r "%cfg_filter%" EI.cfg') do (set EI=%%i& set nID=%%i)
+set EI=& set Name=& set eID=& set reg=& set "cfg_filter=EditionID Channel OEM Retail Volume _Default VL 0 1 ^$"
+if exist EI.cfg for /f "tokens=*" %%i in ('findstr /v /i /r "%cfg_filter%" EI.cfg') do (set EI=%%i& set eID=%%i)
 if exist PID.txt for /f "delims=;" %%i in (PID.txt) do set %%i 2>nul
 if not defined Value for %%s in (%OPTIONS%) do if defined pn_%%s (set Name=!pn_%%s!& set Name=!Name:gvlk=!)
 if defined Value if not defined Name for %%s in (%Value%) do (set Name=!pn_%%s!& set Name=!Name:gvlk=!)
-if defined EDITION_SWITCH (set nID=%EDITION_SWITCH%) else if defined Name for %%s in (%Name%) do (set nID=%Name%)
-if not defined nID set nID=%EditionID%& if not defined EditionID set nID=Professional& set EditionID=Professional
-if /i "%EditionID%" equ "%nID%" (set changed=) else set changed=1
-
-::# upgrade matrix to automatically fallback to an edition that would keep files and apps
-set HOME=Starter HomeBasic HomePremium CoreConnectedCountrySpecific CoreConnectedSingleLanguage CoreConnected Core
-set HOME_N=StarterN HomeBasicN HomePremiumN CoreConnectedN CoreN & set HOME_S=CoreSingleLanguage CoreCountrySpecific
-set ULT=Ultimate ProfessionalStudent ProfessionalCountrySpecific ProfessionalSingleLanguage& set CLOUD=Cloud
-set ULT_N=UltimateN ProfessionalStudentN& set CLOUD_N=CloudN
-set EDU=Education& set ENT=Enterprise& set LTS=EnterpriseG EnterpriseS IoTEnterpriseS Embedded& set IOT=IoTEnterprise
-set EDU_N=EducationN& set ENT_N=EnterpriseN& set LTS_N=EnterpriseGN EnterpriseSN
-set PRO=ProfessionalEducation ProfessionalWorkstation Professional& set MIX=%ENT% %EDU% !PRO! %CLOUD%
-set PRO_N=ProfessionalEducationN ProfessionalWorkstationN ProfessionalN& set MIX_N=%ENT_N% %EDU_N% !PRO_N! %CLOUD_N%
-for %%C in (%LTS_N%)  do if /i %%C equ %nID% (set nID=EnterpriseN)
-for %%C in (%LTS%)    do if /i %%C equ %nID% (set nID=Enterprise)
-for %%C in (%ULT_N%)  do if /i %%C equ %nID% (set nID=ProfessionalN)
-for %%C in (%ULT%)    do if /i %%C equ %nID% (set nID=Professional)
-for %%C in (%MIX_N%)  do if /i %%C equ %nID% (set nID=ProfessionalN& set reg=%%C& if defined i_%%C set nID=%%C)
-for %%C in (%MIX%)    do if /i %%C equ %nID% (set nID=Professional&  set reg=%%C& if defined i_%%C set nID=%%C)
-for %%C in (%HOME_N%) do if /i %%C equ %nID% (set nID=CoreN& set reg=CoreN& if not defined i_CoreN set nID=ProfessionalN)
-for %%C in (%HOME%)   do if /i %%C equ %nID% (set nID=Core&  set reg=Core&  if not defined i_Core  set nID=Professional)
-for %%C in (%HOME_S%) do if /i %%C equ %nID% (set nID=Core& set reg=%%C& if defined i_%%C set nID=%%C)
-for %%C in (%IOT%)    do if /i %%C equ %nID% (set nID=Enterprise& set reg=%%C)
-set index=& for /l %%i in (1,1,%w_count%) do if /i !i_%%i! equ !nID! (set nID=!i_%%i!& set index=%%i)
-if not defined index set index=1& set nID=!i_1!& if defined i_Professional set index=!i_Professional!& set nID=Professional
-set Build=!b_%index%!& set OPTIONS=%OPTIONS% /ImageIndex %index%& if defined changed if not defined reg (set reg=!nID!)
-echo;Current edition: %EditionID% & echo;Regedit edition: %reg% & echo;Index: %index%  Image: %nID%
+if defined EDITION_SWITCH (set eID=%EDITION_SWITCH%) else if defined Name for %%s in (%Name%) do (set eID=%Name%)
+if not defined eID set eID=%EditionID%& if not defined EditionID set eID=Professional& set EditionID=Professional
+if /i "%EditionID%" equ "%eID%" (set changed=) else set changed=1
+
+::# upgrade matrix - now also for Enterprise Eval - automatically pick edition that would keep files and apps
+if /i CoreCountrySpecific equ %eID% set "comp=!eID!" & set "reg=!eID!" & if not defined i_!eID! set "eID=Core"
+if /i CoreSingleLanguage  equ %eID% set "comp=Core"  & set "reg=!eID!" & if not defined i_!eID! set "eID=Core"
+for %%e in (Starter HomeBasic HomePremium CoreConnectedCountrySpecific CoreConnectedSingleLanguage CoreConnected Core) do (
+ if /i %%e  equ %eID% set "comp=Core"  & set "eID=Core"
+ if /i %%eN equ %eID% set "comp=CoreN" & set "eID=CoreN"
+ if /i %%e  equ %eID% if not defined i_Core  set "eID=Professional"  & if not defined reg set "reg=Core"
+ if /i %%eN equ %eID% if not defined i_CoreN set "eID=ProfessionalN" & if not defined reg set "reg=CoreN"
+)
+for %%e in (Ultimate ProfessionalStudent ProfessionalCountrySpecific ProfessionalSingleLanguage) do (
+  if /i %%e equ %eID% (set "eID=Professional") else if /i %%eN equ %eID% set "eID=ProfessionalN"
+)
+for %%e in (EnterpriseG EnterpriseS IoTEnterpriseS IoTEnterprise Embedded) do (
+  if /i %%e equ %eID% (set "eID=Enterprise") else if /i %%eN equ %eID% set "eID=EnterpriseN"
+)
+for %%e in (Enterprise EnterpriseS) do (
+  if /i %%eEval equ %eID% (set "eID=Enterprise") else if /i %%eNEval equ %eID% set "eID=EnterpriseN"
+)
+if /i Enterprise  equ %eID% set "comp=!eID!" & if not defined i_!eID! set "eID=Professional"  & set "reg=!comp!"
+if /i EnterpriseN equ %eID% set "comp=!eID!" & if not defined i_!eID! set "eID=ProfessionalN" & set "reg=!comp!"
+for %%e in (Education ProfessionalEducation ProfessionalWorkstation Professional Cloud) do (
+  if /i %%eN equ %eID% set "comp=EnterpriseN"  & if not defined reg set "reg=%%eN"
+  if /i %%e  equ %eID% set "comp=Enterprise"   & if not defined reg set "reg=%%e"
+  if /i %%eN equ %eID% set "eID=ProfessionalN" & if defined i_%%eN  set "eID=%%eN"
+  if /i %%e  equ %eID% set "eID=Professional"  & if defined i_%%e   set "eID=%%e"
+)
+set index=& set lst=Professional& for /l %%i in (1,1,%w_count%) do if /i !i_%%i! equ !eID! set "index=%%i" & set "eID=!i_%%i!" 
+if not defined index set index=1& set eID=!i_1!& if defined i_%lst% set "index=!i_%lst%!" & set "eID=%lst%"& set "comp=Enterprise"
+set Build=!b_%index%!& set OPTIONS=%OPTIONS% /ImageIndex %index%& if defined changed if not defined reg set "reg=!eID!"
+echo;Current edition: %EditionID% & echo;Regedit edition: %reg% & echo;Index: %index%  Image: %eID%
 timeout /t 10
 
+::# disable upgrade blocks
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f /v DisableWUfBSafeguards /d 1 /t reg_dword >nul 2>nul  
+
 ::# prevent usage of MCT for intermediary upgrade in Dynamic Update (causing 7 to 19H1 instead of 7 to 21H2 for example) 
 if "%Build%" gtr "15063" (set OPTIONS=%OPTIONS% /UpdateMedia Decline)
 
-::# skip windows 11 upgrade checks via launch option trick - this way, can still run setup.exe directly to not skip checks
-if "%Build%" geq "22000" if "%SKIP_11_SETUP_CHECKS%" equ "1" (set OPTIONS=/Product Server %OPTIONS%)
+::# skip windows 11 upgrade checks: add launch option trick if old-style 0-byte file trick is not on the media  
+if "%Build%" lss "22000" set /a SKIP_11_SETUP_CHECKS=0
+reg add HKLM\SYSTEM\Setup\MoSetup /f /v AllowUpgradesWithUnsupportedTPMorCPU /d 1 /t reg_dword >nul 2>nul &rem ::# TPM 1.2+ only
+if "%SKIP_11_SETUP_CHECKS%" equ "1" cd.>appraiserres.dll 2>nul & rem ::# writable media only
+for %%A in (appraiserres.dll) do if %%~zA gtr 0 (set TRICK=/Product Server ) else (set TRICK=)
+if "%SKIP_11_SETUP_CHECKS%" equ "1" (set OPTIONS=%TRICK%%OPTIONS%)
 
 ::# auto upgrade with edition lie workaround to keep files and apps - all 1904x builds allow up/downgrade between them
 if defined reg call :rename %reg%
 start "auto" setupprep.exe %OPTIONS%
-exit /b
+echo;DONE
+
+EXIT /b
 
 :rename EditionID
-set NT="HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
-(reg query %NT% /v ProductName_undo      /reg:32 || reg add %NT% /v ProductName_undo /d "%ProductName%" /f /reg:32
- reg query %NT% /v ProductName_undo      /reg:64 || reg add %NT% /v ProductName_undo /d "%ProductName%" /f /reg:64
- reg query %NT% /v EditionID_undo        /reg:32 || reg add %NT% /v EditionID_undo   /d "%EditionID%"   /f /reg:32
- reg query %NT% /v EditionID_undo        /reg:64 || reg add %NT% /v EditionID_undo   /d "%EditionID%"   /f /reg:64
- reg add   %NT% /v EditionID /d "%~1" /f /reg:32 &  reg add %NT% /v ProductName      /d "%~1"           /f /reg:32
- reg add   %NT% /v EditionID /d "%~1" /f /reg:64 &  reg add %NT% /v ProductName      /d "%~1"           /f /reg:64
-) >nul 2>nul &exit /b
+set "NT=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
+for %%v in (CompositionEditionID EditionID ProductName) do reg add "%NT%" /v %%v_undo /d "!%%v!" /f >nul 2>nul
+for %%A in (32 64) do ( 
+ reg add "%NT%" /v CompositionEditionID /d "%comp%" /f /reg:%%A
+ reg add "%NT%" /v EditionID /d "%~1" /f /reg:%%A
+ reg add "%NT%" /v ProductName /d "%~1" /f /reg:%%A
+) >nul 2>nul
+exit /b
+
+:reg_query [USAGE] call :reg_query "HKCU\Volatile Environment" Value variable
+(for /f "tokens=2*" %%R in ('reg query "%~1" /v "%~2" /se "|" %4 2^>nul') do set "%~3=%%S") & exit /b
 
 #:WIM_INFO:# [PARAMS]: "file" [optional]Index or 0 = all  Output 0 = txt 1 = xml 2 = file.txt 3 = file.xml 4 = xml object
-set ^ #=$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#[:]WIM_INFO[:]' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
+set ^ #=;$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#[:]WIM_INFO[:]' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
 set ^ #=& set "0=%~f0"& set 1=;WIM_INFO %*& powershell -nop -c "%#%"& exit /b %errorcode%
 function WIM_INFO ($file = 'install.esd', $index = 0, $out = 0) { :info while ($true) {
   $block = 2097152; $bytes = new-object 'Byte[]' ($block); $begin = [uint64]0; $final = [uint64]0; $limit = [uint64]0
@@ -722,74 +792,104 @@ function WIM_INFO ($file = 'install.esd', $index = 0, $out = 0) { :info while ($
 } #:WIM_INFO:# Quick WIM SWM ESD ISO info v2 - lean and mean snippet by AveYo, 2021
 
 '@; [io.file]::WriteAllText('auto.cmd', $text) #:generate_auto_cmd
-::--------------------------------------------------------------------------------------------------------------------------------
 
+::--------------------------------------------------------------------------------------------------------------------------------
 :generate_AutoUnattend_xml $text = @'
-<unattend xmlns="urn:schemas-microsoft-com:unattend"><!-- offline local account on 11 Home editions and privacy opt-out -->  
+<unattend xmlns="urn:schemas-microsoft-com:unattend">
   <settings pass="windowsPE"><component name="Microsoft-Windows-Setup" processorArchitecture="amd64" language="neutral"
-    xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
-  <UserData><ProductKey><Key>AAAAA-VVVVV-EEEEE-YYYYY-OOOOO</Key><WillShowUI>OnError</WillShowUI></ProductKey></UserData>
+   xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
+    <UserData><ProductKey><Key>AAAAA-VVVVV-EEEEE-YYYYY-OOOOO</Key><WillShowUI>OnError</WillShowUI></ProductKey></UserData>
+    <ComplianceCheck><DisplayReport>Never</DisplayReport></ComplianceCheck><Diagnostics><OptIn>false</OptIn></Diagnostics>
+    <DynamicUpdate><Enable>true</Enable><WillShowUI>Never</WillShowUI></DynamicUpdate><EnableNetwork>true</EnableNetwork>
+  </component></settings>  
+  <settings pass="specialize"><component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" language="neutral"
+   xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
+    <RunSynchronous>
+      <!-- offline local account via OOBE\BYPASSNRO on every site but literally no one credits AveYo for sharing it -->
+      <RunSynchronousCommand wcm:action="add"><Order>1</Order>
+        <Path>reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE /v BypassNRO /t reg_dword /d 1 /f</Path>
+      </RunSynchronousCommand>
+      <!-- hide unsupported nag on update settings - 25H1 is not a typo ;) -->
+      <RunSynchronousCommand wcm:action="add"><Order>2</Order>
+        <Path>reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v TargetReleaseVersion /d 1 /t reg_dword /f</Path>
+      </RunSynchronousCommand>
+      <RunSynchronousCommand wcm:action="add"><Order>3</Order>
+        <Path>reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v TargetReleaseVersionInfo /d 25H1 /f</Path>
+      </RunSynchronousCommand>
+    </RunSynchronous>
   </component></settings>
   <settings pass="oobeSystem"><component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" language="neutral" 
-    xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
-  <OOBE><HideOnlineAccountScreens>true</HideOnlineAccountScreens><HideLocalAccountScreen>false</HideLocalAccountScreen>
-  <HideWirelessSetupInOOBE>false</HideWirelessSetupInOOBE><ProtectYourPC>3</ProtectYourPC></OOBE></component></settings>
+   xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
+    <OOBE>
+      <HideLocalAccountScreen>false</HideLocalAccountScreen><HideOnlineAccountScreens>false</HideOnlineAccountScreens>
+      <HideWirelessSetupInOOBE>false</HideWirelessSetupInOOBE><ProtectYourPC>3</ProtectYourPC>
+    </OOBE>  
+    <FirstLogonCommands>
+      <!-- hide unsupported nag on desktop - originally shared by awuctl @ MDL -->
+      <SynchronousCommand wcm:action="add"><Order>1</Order>
+        <CommandLine>reg add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v SV1 /d 0 /t reg_dword /f</CommandLine>
+      </SynchronousCommand><SynchronousCommand wcm:action="add"><Order>2</Order>
+        <CommandLine>reg add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v SV2 /d 0 /t reg_dword /f</CommandLine>
+      </SynchronousCommand>
+    </FirstLogonCommands>
+  </component></settings>
 </unattend>
 
-'@; [io.file]::WriteAllText('AutoUnattend.xml', $text); #:generate_AutoUnattend_xml - to be used via boot.wim 
-::--------------------------------------------------------------------------------------------------------------------------------
+'@; [io.file]::WriteAllText('AutoUnattend.xml', $text); #:generate_AutoUnattend_xml - to be used via boot.wim on 11
 
+::--------------------------------------------------------------------------------------------------------------------------------
 :reg_query [USAGE] call :reg_query "HKCU\Volatile Environment" Value variable
 (for /f "tokens=2*" %%R in ('reg query "%~1" /v "%~2" /se "," 2^>nul') do set "%~3=%%S")& exit /b
-::--------------------------------------------------------------------------------------------------------------------------------
 
-#:DIR2ISO:#  [PARAMS] "directory" "file.iso" [optional]"label"
-set ^ #=$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#\:DIR2ISO\:' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
-set ^ #=& set "0=%~f0"& set 1=;DIR2ISO %*& powershell -nop -c "%#%"& exit /b %errorcode%
-function DIR2ISO ($dir,$iso,$label='DVD_ROM') {if (!(test-path -Path $dir -pathtype Container)) {"[ERR] $dir"; return 1}; $code=@"
+::--------------------------------------------------------------------------------------------------------------------------------
+#:MakeISO:#  [PARAMS] "directory" "file.iso" [optional]"label"
+set ^ #=;$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#\:MakeISO\:' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
+set ^ #=& set "0=%~f0"& set 1=;MakeISO %*& powershell -nop -c "%#%"& exit /b %errorcode%
+function MakeISO ($dir,$iso,$label='DVD_ROM') {if (!(test-path -Path $dir -pathtype Container)) {"[ERR] $dir"; return 1}; $code=@"
  using System; using System.IO; using System.Runtime.Interop`Services; using System.Runtime.Interop`Services.ComTypes;
  public class dir2iso {public int AveYo=2021; [Dll`Import("shlwapi",CharSet=CharSet.Unicode,PreserveSig=false)]
  internal static extern void SHCreateStreamOnFileEx(string f,uint m,uint d,bool b,IStream r,out IStream s);
  public static int Create(string file, ref object obj, int bs, int tb) { IStream dir=(IStream)obj, iso;
  try {SHCreateStreamOnFileEx(file,0x1001,0x80,true,null,out iso);} catch(Exception e) {Console.WriteLine(e.Message); return 1;}
  int d=tb>1024 ? 1024 : 1, pad=tb%d, block=bs*d, total=(tb-pad)/d, c=total>100 ? total/100 : total, i=1, MB=(bs/1024)*tb/1024;
- Console.Write("{0,2}%  {1}MB {2}  DIR2ISO",0,MB,file); if (pad > 0) dir.CopyTo(iso, pad * block, Int`Ptr.Zero, Int`Ptr.Zero);
+ Console.Write("{0}\r\n{1,2}%  {2}MB  MakeISO",file,0,MB); if (pad > 0) dir.CopyTo(iso, pad * block, Int`Ptr.Zero, Int`Ptr.Zero);
  while (total-- > 0) {dir.CopyTo(iso, block, Int`Ptr.Zero, Int`Ptr.Zero); if (total % c == 0) {Console.Write("\r{0,2}%",i++);}}
- iso.Commit(0); Console.WriteLine("\r{0,2}%  {1}MB {2}  DIR2ISO",100,MB,file); return 0;} }
+ iso.Commit(0); Console.WriteLine("\r{0,2}%  {1}MB  MakeISO",100,MB); return 0;} }
 "@; & { $cs = new-object CodeDom.Compiler.CompilerParameters; $cs.GenerateInMemory = 1 #:: ` used to silence ps eventlog
  $compile = (new-object Microsoft.CSharp.CSharpCodeProvider).CompileAssemblyFromSource($cs, $code)
  $BOOT = @(); $bootable = 0; $mbr_efi = @(0,0xEF); $images = @('boot\etfsboot.com','efi\microsoft\boot\efisys.bin') #:: _noprompt
  0,1|% { $bootimage = join-path $dir -child $images[$_]; if (test-path -Path $bootimage -pathtype Leaf) {
  $bin = new-object -ComObject ADODB.Stream; $bin.Open(); $bin.Type = 1; $bin.LoadFromFile($bootimage)
- $opt = new-object -ComObject IMAPI2FS.BootOptions;$opt.AssignBootImage($bin.psobject.BaseObject); $opt.PlatformId = $mbr_efi[$_] 
+ $opt = new-object -ComObject IMAPI2FS.BootOptions;$opt.AssignBootImage($bin.psobject.BaseObject); $opt.PlatformId = $mbr_efi[$_]
  $opt.Emulation = 0; $bootable = 1; $opt.Manufacturer = 'Microsoft'; $BOOT += $opt.psobject.BaseObject } }
  $fsi = new-object -ComObject IMAPI2FS.MsftFileSystemImage; $fsi.FileSystemsToCreate = 4; $fsi.FreeMediaBlocks = 0
  if ($bootable) {$fsi.BootImageOptionsArray = $BOOT}; $TREE = $fsi.Root; $TREE.AddTree($dir,$false); $fsi.VolumeName = $label
  $obj = $fsi.CreateResultImage(); $ret = [dir2iso]::Create($iso,[ref]$obj.ImageStream,$obj.BlockSize,$obj.TotalBlocks) }
  [GC]::Collect(); return $ret
-} #:DIR2ISO:#  export directory as (bootable) udf iso - lean and mean snippet by AveYo, 2021
-::--------------------------------------------------------------------------------------------------------------------------------
+} #:MakeISO:#  export directory as (bootable) udf iso - lean and mean snippet by AveYo, 2022.03.15
 
+::--------------------------------------------------------------------------------------------------------------------------------
 #:DOWNLOAD:# [PARAMS] "url" "file" [optional]"path"
-set ^ #=$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#\:DOWNLOAD\:' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
+set ^ #=;$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#\:DOWNLOAD\:' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
 set ^ #=& set "0=%~f0"& set 1=;DOWNLOAD %*& powershell -nop -c "%#%"& exit /b %errorcode%
 function DOWNLOAD ($u, $f, $p = (get-location).Path) {
-  Import-Module BitsTransfer; $wc = new-object Net.WebClient; $wc.Headers.Add('user-agent','ipad'); $j = 2022 
-  $file = join-path $p $f; $s = 'https://'; $i = 'http://'; $d = $u.replace($s,'').replace($i,''); $https = $s+$d; $http = $i+$d 
-  foreach ($url in $http, $https) { 
-    if (([IO.FileInfo]$file).Exists) {return}; try {Start-BitsTransfer $($url+'/?') $file -ea 1} catch {}
-    if (([IO.FileInfo]$file).Exists) {return}; try {bitsadmin /transfer ($j++) /download /priority FOREGROUND $url $file} catch {}
-    if (([IO.FileInfo]$file).Exists) {return}; try {$wc.DownloadFile($url+'/?', $file)} catch {}
-    if (([IO.FileInfo]$file).Exists) {return}; try {curl -so $file $url} catch {}
-  }  
+  $null = Import-Module BitsTransfer -ea 0; $wc = new-object Net.WebClient; $wc.Headers.Add('user-agent','ipad')
+  $file = join-path $p $f; $s = 'https://'; $i = 'http://'; $d = $u.replace($s,'').replace($i,''); $https = $s+$d; $http = $i+$d
+  foreach ($url in $http, $https) {
+    if (([IO.FileInfo]$file).Exists) {return}; try {Start-BitsTransfer $url $file -ea 1} catch {}
+    if (([IO.FileInfo]$file).Exists) {return}; try {Invoke-WebRequest $url -OutFile $file} catch {} ; $j = (Get-Date).Ticks
+    if (([IO.FileInfo]$file).Exists) {return}; try {$null = bitsadmin /transfer $j /priority foreground $url $file} catch {}
+    if (([IO.FileInfo]$file).Exists) {return}; try {$wc.DownloadFile($url, $file)} catch {}
+  }
   if (([IO.FileInfo]$file).Exists) {return}; write-host -fore Yellow " $f download failed "
 } #:DOWNLOAD:# try download url via bits, net, and http/https - snippet by AveYo, 2021
-::--------------------------------------------------------------------------------------------------------------------------------
 
+::--------------------------------------------------------------------------------------------------------------------------------
 #:CHOICES:#  [PARAMS] indexvar "c,h,o,i,c,e,s"  [OPTIONAL]  default-index "title" fontsize backcolor forecolor winsize
-set ^ #=$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#\:CHOICES\:' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
+set ^ #=;$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#\:CHOICES\:' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
 set ^ #=&set "0=%~f0"& set 1=;CHOICES %*& (for /f %%x in ('powershell -nop -c "%#%"') do set "%1=%%x")& exit /b
 function CHOICES ($index,$choices,$def=1,$title='Choices',[int]$sz=12,$bc='MidnightBlue',$fc='Snow',[string]$win='300') {
  [void][Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); $f=new-object Windows.Forms.Form; $global:ret=''
@@ -799,12 +899,12 @@ function CHOICES ($index,$choices,$def=1,$title='Choices',[int]$sz=12,$bc='Midni
  $b.FlatStyle=0; $b.Cursor='Hand'; $b.add_Click({$global:ret=$this.Name;$f.Close()}); $f.Controls.Add($b); $bt+=$b; $i++}
  $f.Text=$title; $f.BackColor=$bc; $f.ForeColor=$fc; $f.StartPosition=4; $f.AutoSize=1; $f.AutoSizeMode=0; $f.MaximizeBox=0
  $f.AcceptButton=$bt[$def-1]; $f.CancelButton=$bt[-1]; $f.Add_Shown({$f.Activate();$bt[$def-1].focus()})
- $f.ShowDialog() >''; $index=$global:ret; if ($index -eq $ch.length) {return 0} else {return $index}
+ $f.ShowDialog() >$null; $index=$global:ret; if ($index -eq $ch.length) {return 0} else {return $index}
 } #:CHOICES:#  gui dialog with inverted focus returning selected index - lean and mean snippet by AveYo, 2018 - 2021
-::--------------------------------------------------------------------------------------------------------------------------------
 
+::--------------------------------------------------------------------------------------------------------------------------------
 #:CHOICES2:#  [INTERNAL]
-set ^ #=$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#\:CHOICES2\:' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
+set ^ #=;$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#\:CHOICES2\:' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
 set ^ #=&set "0=%~f0"&set 1=;CHOICES2 %*&(for /f "tokens=1,2" %%x in ('powershell -nop -c "%#%"')do set %1=%%x&set %5=%%y)&exit /b
 function CHOICES2 {iex($f0-split '#\:CHOICES\:' ,3)[1]; function :LOOP { $a=$args
  $c1 = @($a[0], $a[1], $a[2], $a[3],  $a[-4], $a[-3], $a[-2], $a[-1]); $r1= CHOICES @c1; if ($r1 -lt 1) {return "0 0"}
@@ -812,11 +912,11 @@ function CHOICES2 {iex($f0-split '#\:CHOICES\:' ,3)[1]; function :LOOP { $a=$arg
  $c2 = @($a[4], $a[5], $a[6], $a_7_,  $a[-4], $a[-3], $a[-2], $a[-1]); $r2= CHOICES @c2; if ($r2 -ge 1) {return "$r1 $r2"}
  if ($r2 -lt 1) {$a[2]=$r1; :LOOP @a} }; :LOOP @args #:: index1 choices1 def1 title1  index2 choices2 def2 title2  font bc tc win
 } #:CHOICES2:#  MediaCreationTool.bat gui pseudo-menu via CHOICES snippet, streamlined in a single powershell instance
-::--------------------------------------------------------------------------------------------------------------------------------
 
+::--------------------------------------------------------------------------------------------------------------------------------
 #:PRODUCTS_XML:#  [INTERNAL]    refactored with less looping over Files; addressed more powershell 2.0 quirks
-set ^ #=$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#\:PRODUCTS_XML\:' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
-set ^ #=& set "0=%~f0"& set 1=;PRODUCTS_XML %*& powershell -nop -c "%#%"& exit /bat/ps1
+set ^ #=;$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#\:PRODUCTS_XML\:' ,3)[1]; $1=$env:1-replace'([`@$])','`$1';iex($0+$1)
+set ^ #=& set "0=%~f0"& set 1=;PRODUCTS_XML %*& powershell -nop -c "%#%"& exit /b
 function PRODUCTS_XML { [xml]$xml = [io.file]::ReadAllText("$pwd\products.xml",[Text.Encoding]::UTF8); $root = $null
  $eulas = 0; $langs = 0; $ver = $env:VER; $vid = $env:VID; $X = $env:X; if ($X-eq'11') {$vid = "11 $env:VIS"}
  $url = "http://b1.download.windowsupdate.com/"
@@ -825,7 +925,7 @@ function PRODUCTS_XML { [xml]$xml = [io.file]::ReadAllText("$pwd\products.xml",[
    $xml.MCT.Catalogs.Catalog.version = $env:CC; $root = $xml.SelectSingleNode('/MCT/Catalogs/Catalog/PublishedMedia')
  } else {
    $temp = [xml]('<?xml version="1.0" encoding="UTF-8"?><MCT><Catalogs><Catalog version="' + $env:CC + '"/></Catalogs></MCT>')
-   $temp.SelectSingleNode('/MCT/Catalogs/Catalog').AppendChild($temp.ImportNode($xml.PublishedMedia,$true)) >''
+   $temp.SelectSingleNode('/MCT/Catalogs/Catalog').AppendChild($temp.ImportNode($xml.PublishedMedia,$true)) >$null
    $xml = $temp; $root = $xml.SelectSingleNode('/MCT/Catalogs/Catalog/PublishedMedia')
  }
  foreach ($l in $root.ChildNodes) {if ($l.LocalName -eq 'EULAS') {$eulas = 1}; if ($l.LocalName -eq 'Languages') {$langs = 1} }
@@ -838,29 +938,29 @@ function PRODUCTS_XML { [xml]$xml = [io.file]::ReadAllText("$pwd\products.xml",[
      $i = $el.AppendChild($node.Clone()); $lc = $lang.LanguageCode
      $i.LanguageCode = $lc; $i.URL = $eula + $lc.ToUpperInvariant() + '_6.27.16.rtf'
    }
-   $root.AppendChild($el) >''
+   $root.AppendChild($el) >$null
  }
 #:: friendlier version + combined consumer editions label (not doing it for business too here as it would be ignored by mct)
  if ($langs -eq 1) {
-   if ($ver -gt 15063) {$CONSUMER = "$vid Home | Pro | Edu"} else {$CONSUMER = "$vid Home | Pro"} #:: 1511
+   if ($ver -gt 15063) {$CONSUMER = "$vid Pro | Edu | Home"} else {$CONSUMER = "$vid Pro | Home"} #:: 1511
    foreach ($i in $root.Languages.Language) {
      foreach ($l in $i.ChildNodes) { $l.InnerText = $l.InnerText.replace("Windows 10", $vid) }
      if ($null -ne $i.CLIENT)    {$i.CLIENT   = "$CONSUMER"}    ;  if ($null -ne $i.CLIENT_K)  {$i.CLIENT_K  = "$CONSUMER K"}
      if ($null -ne $i.CLIENT_N)  {$i.CLIENT_N = "$CONSUMER N"}  ;  if ($null -ne $i.CLIENT_KN) {$i.CLIENT_KN = "$CONSUMER KN"}
    }
  }
- $BUSINESS = "$vid Enterprise | Pro vl | Edu vl"
+ $BUSINESS = "$vid Pro | Edu | Enterprise"
  $root.Files.File | & { process {
    $_arch = $_.Architecture; $_lang = $_.LanguageCode; $_edi = $_.Edition; $_loc = $_.Edition_Loc; $ok = $true
   #:: clear ARM64 and %BASE_CHINA% entries to simplify processing - TODO: ARM support
-   if ($_arch -eq 'ARM64' -or ($ver -lt 22000 -and $_loc -eq '%BASE_CHINA%')) {$root.Files.RemoveChild($_) >''; return}
+   if ($_arch -eq 'ARM64' -or ($ver -lt 22000 -and $_loc -eq '%BASE_CHINA%')) {$root.Files.RemoveChild($_) >$null; return}
   #:: unhide combined business editions in xml that include them: 1709 - 21H1; unhide Education on 1507 - 1511; better label
    if ($env:UNHIDE_BUSINESS -ge 1) {
      if ($_edi -eq 'Enterprise' -or $_edi -eq 'EnterpriseN') {$_.IsRetailOnly = 'False'; $_.Edition_Loc = $BUSINESS}
      if ($ver -le 15063 -and ($_edi -eq 'Education' -or $_edi -eq 'EducationN')) {$_.IsRetailOnly = 'False'} #:: 1511
    }
  }}
- $lines = ([io.file]::ReadAllText($env:0)-split':PS_INSERT_BUSINESS_CSV\:')[1]; $insert = $false
+ $lines = ([io.file]::ReadAllText($env:0) -split':PS_INSERT_BUSINESS_CSV\:')[1]; $insert = $false
  if ($null -ne $lines -and $env:INSERT_BUSINESS -ge 1 -and 19043,19042,19041,18363,15063,14393 -contains $ver) {
    $csv = ConvertFrom-CSV -Input $lines.replace('sr-rs','sr-latn-rs') | & { process { if ($_.Ver -eq $ver) {$_} } }
    $edi = @{ent='Enterprise';enN='EnterpriseN';edu='Education';edN='EducationN';clo='Cloud';clN='CloudN';
@@ -878,12 +978,12 @@ function PRODUCTS_XML { [xml]$xml = [io.file]::ReadAllText("$pwd\products.xml",[
      $root.Files.File | & { process { if ($_.Edition -eq "Education") {
        $arch = $_.Architecture; $lang = $_.LanguageCode; $item = $items[$lang]; if ($null -eq $item) {return}
        if ($arch -eq 'x64')     {$_size = $item[0].Size_x64; $_sha1 = $item[0].Sha1_x64; $_dir = $item[0].Dir_x64}
-       elseif ($arch -eq 'x86') {$_size = $item[0].Size_x86; $_sha1 = $item[0].Sha1_x86; $_dir = $item[0].Dir_x86} 
+       elseif ($arch -eq 'x86') {$_size = $item[0].Size_x86; $_sha1 = $item[0].Sha1_x86; $_dir = $item[0].Dir_x86}
        $c = $_.Clone(); if ($c.HasAttribute('id')) {$c.RemoveAttribute('id')} $c.IsRetailOnly = 'False'; $c.Edition = $edi[$e]
        $name = $env:CB + $cli + $arch + 'FRE_' + $lang; $c.Edition_Loc = "$vid $BUSINESS"
        $c.FileName = $name + '.esd'; $c.Size = $_size; $c.Sha1 = $_sha1
        $c.FilePath = $url + $_dir + $up + $env:CT + $name.ToLowerInvariant() + '_' + $_sha1 + '.esd'
-       $root.Files.AppendChild($c) >''
+       $root.Files.AppendChild($c) >$null
      }}}
    }
  }
@@ -896,8 +996,8 @@ function PRODUCTS_XML { [xml]$xml = [io.file]::ReadAllText("$pwd\products.xml",[
        if ($edition -eq 'Enterprise' -or $edition -eq 'EnterpriseN') {$cli = '_CLIENTBUSINESS_'; $chan = 'vol'}
        $arch = $_.Architecture; $lang = $_.LanguageCode; $item = $items["$chan, $lang"]; if ($null -eq $item) {return}
        if ($arch -eq 'x64')     {$_size = $item[0].Size_x64; $_sha1 = $item[0].Sha1_x64; $_dir = $item[0].Dir_x64}
-       elseif ($arch -eq 'x86') {$_size = $item[0].Size_x86; $_sha1 = $item[0].Sha1_x86; $_dir = $item[0].Dir_x86} 
-       if ('' -eq $_size) {$root.Files.RemoveChild($_) >''; return}
+       elseif ($arch -eq 'x86') {$_size = $item[0].Size_x86; $_sha1 = $item[0].Sha1_x86; $_dir = $item[0].Dir_x86}
+       if ('' -eq $_size) {$root.Files.RemoveChild($_) >$null; return}
        $name = $env:CB + $cli + $chan.ToUpperInvariant() + '_' + $arch + 'FRE_' + $_.LanguageCode
        $_.FileName = $name + '.esd'; $_.Size = $_size; $_.Sha1 = $_sha1
        $_.FilePath = $url + $_dir + '/upgr/' + $env:CT + $name.ToLowerInvariant() + '_' + $_sha1 + '.esd'
@@ -914,21 +1014,21 @@ function PRODUCTS_XML { [xml]$xml = [io.file]::ReadAllText("$pwd\products.xml",[
      if ($_.Edition -eq $source) {
        foreach ($s in $clone) {
          $c = $_.Clone(); if ($c.HasAttribute('id')) {$c.RemoveAttribute('id')}
-         $c.IsRetailOnly='False'; $c.Edition=$s; $root.Files.AppendChild($c) >''
+         $c.IsRetailOnly='False'; $c.Edition=$s; $root.Files.AppendChild($c) >$null
        }
      }
      elseif ($_.Edition -eq $sourceN) {
        foreach ($s in $cloneN) {
          $c = $_.Clone(); if ($c.HasAttribute('id')) {$c.RemoveAttribute('id')}
-         $c.IsRetailOnly='False'; $c.Edition=$s; $root.Files.AppendChild($c) >''
+         $c.IsRetailOnly='False'; $c.Edition=$s; $root.Files.AppendChild($c) >$null
        }
    }}}
  }
  $xml.Save("$pwd\products.xml");
 
 } #:PRODUCTS_XML:#  MediaCreationTool.bat configuring products.xml in one go
-::--------------------------------------------------------------------------------------------------------------------------------
 
+::--------------------------------------------------------------------------------------------------------------------------------
 ::# Insert business esd links in 1607,1703; Update 1909,2004,20H2,21H2 by hand until an updated products.xml from microsoft
 ::# Following are condensed ver,edition,lang,sizes,hashes,dirs to be recomposed into full official ESD links for MCT
 ::# I have chosen to generate them on-the-fly here instead of linking to third-party hosted pre-edited products.xml

+ 26 - 61
README.md

@@ -1,6 +1,7 @@
 Not just an Universal MediaCreationTool wrapper script with ingenious support for business editions,  
 <img src="preview.png">  
 A powerful yet simple windows 10 / 11 deployment automation tool as well!  
+*If you had no success launching the script so far, this latest version will work*  
 
 Presets  
 -------  
@@ -8,9 +9,11 @@ Presets
 > _- can keep files and apps on more scenarios where os and target edition does not match_  
 > _- can switch detected edition by adding EditionID to script name_  
 > _- can troubleshoot upgrade failing by adding `no_update` to script name_  
+> _- auto defaults to 11, so pass version as well for 10: `auto 21H2 MediaCreationTool.bat`_  
 
 2 ***Auto ISO*** with detected media in current folder directly _(or C:\ESD if run from zip)_  
 > _- can override detected media by adding edition name / language / arch to script name_  
+> _- example: `21H1 Education en-US x86 iso MediaCreationTool.bat`_  
 
 3 ***Auto USB*** with detected media in specified usb target  
 > _- for data safety, this is not fully automated - must select the usb drive manually in GUI_  
@@ -19,32 +22,37 @@ Presets
 > _- implicit choice, includes setup override files (disable by adding `def` to script name)_  
 
 5 ***MCT Defaults*** runs unassisted, creating media without script modification  
-> _- no added files, script passes `products.xml` and quits without touching media_  
+> _- no added files, script passes `products.xml` to MCT and quits without touching media_  
 
 1-4 presets will modify created media in the following ways:  
-> _- write `auto.cmd` to run on demand from media for auto upgrade with edition switch support and skip tpm_  
-> _- write `$OEM$` folder (if it exists) with post setup tweaks like `$OEM$\$$\Setup\Scripts\setupcomplete.cmd`_  
-> _- write `sources\PID.txt` to preselect edition at media boot or setup within windows (if configured)_  
+> _- write `auto.cmd` to run on demand for auto upgrade with edition switch and skip tpm_  
+> _- write `$ISO$` folder content (if it exists) at the root of the media_  
+> _if you previously used $OEM$ content, must now place it in `$ISO$\sources\$OEM$\`_  
+> _- write `sources\PID.txt` to preselect edition at media boot or within windows (if configured)_  
 > _- write `sources\EI.cfg` to prevent product key prompt on Windows 11 consumer media (11 only)_  
 > _- write `AutoUnattend.xml` in boot.wim to enable local account on Windows 11 Home (11 only)_  
 > _- patch `winsetup.dll` in boot.wim to remove windows 11 setup checks when booting from media (11 only)_  
-> _- can disable by adding `def` to script name_  
+> _- can disable by adding `def` to script name for a default, untouched MCT media_  
 
 Simple deployment  
 -----------------   
-**auto.cmd** is behind ***Auto Upgrade*** preset via GUI,  
-or fully unnatended by renaming script with `auto MediaCreationTool.bat`  
-Should make it easy to upgrade keeping files and apps when the OS edition does not match the created media  
+**auto.cmd** is behind ***Auto Upgrade*** preset via GUI  
+Can run it fully unnatended by renaming script with `auto MediaCreationTool.bat`  
+Makes it easy to upgrade keeping files and apps when the OS edition does not match the media  
+Should allow upgrade from Ultimate, PosReady, Embedded, LTSC or Enterprise Eval as well  
+
 Generated script is added to the created media so you can run it again at any time  
-It is fairly generic - it will detect available editions in install.esd, pick a suitable index, then  
-update EditionID in the registry to match target; can even force upgrade to another edition, keeping files and apps!  
-Also sets recommended setup options with least amount of issues on upgrades  
+It is fairly generic - it will detect available editions in install.esd, pick a suitable index,  
+then set EditionID in the registry to match; can even force another edition, keeping files and apps!  
+On 11, it will try to skip setup checks (can disable this behavior with script var)  
+Finally, it sets recommended setup options with least amount of issues on upgrades  
 
 > Let's say the current OS is Enterprise LTSC 2019, and you use the business media to upgrade:  
 > **auto.cmd** selects Enterprise index and adjust EditionID to Enterprise in the registry (backed up as EditionID_undo)  
 > Maybe you also want to switch edition,  
 > ex. by renaming the script to  `ProfessionalWorkstation MediaCreationTool.bat`:  
 > **auto.cmd** selects Professional index and sets EditionID to ProfessionalWorkstation in the registry.  
+>   
 > Let's say the OS is Windows 7 Ultimate or PosReady, and you use the consumer media to upgrade:  
 > **auto.cmd** selects Professional index, and sets EditionID to Professional or Enterprise, respectively.  
 > In all cases, the script tries to pick an existing index, else a compatible one to keep files and apps on upgrade.  
@@ -52,57 +60,9 @@ Also sets recommended setup options with least amount of issues on upgrades
 > Let's say you have a dozen PCs spread with versions: 7, 8.1, 10 and editions: Ultimate, Home, Enterprise LTSB..  
 > If you need to upgrade all to the latest 10 version and only use Pro, you could rename the script as:  
 > `auto 21H2 Pro MediaCreationTool.bat`  
+>
 > Can even add a VL / MAK / retail product key in the same way to take care of licensing differences.  
-> The script also picks up any `$OEM$` folder in the current location - for unified branding, configuration, tweaks etc.  
-
-
-Windows 11 and the TPM / SecureBoot / CPU / Storage setup checks  
-----------------------------------------------------------------  
-[MediaCreationTool.bat](MediaCreationTool.bat) creates 11 media that will **automatically skip clean install checks**  
-***Auto Upgrade*** preset, or launching `auto.cmd` from the created media will **automatically skip upgrade checks**  
-Running `setup.exe` from the created media does not bypass setup checks - use `auto.cmd` instead!  
-To NOT add bypass to the media, use ***MCT Defaults*** preset or rename the script as `def MediaCreationTool.bat`  
-
-> Regarding the bypass method, for a more reliable and future-proof experience,  
-> clean installation is still handled via _winsetup.dll_ patching in _boot.wim_  
-> upgrade is now handled only via `auto.cmd` with the */Product Server* trick  
-> *Just ignore the 'Windows Server' label, please!*  
-Note that [Skip_TPM_Check_on_Dynamic_Update.cmd](bypass11/Skip_TPM_Check_on_Dynamic_Update.cmd) acts globally and **will skip upgrade checks via setup.exe**  
-
-Get 11 via Windows Update on "unsupported" hardware  
----------------------------------------------------  
-Step 1: use [Skip_TPM_Check_on_Dynamic_Update.cmd](bypass11/Skip_TPM_Check_on_Dynamic_Update.cmd) to automatically bypass setup requirements  
-_It's a set it and forget it script, with built-in undo - v7 using more reliable /Product Server trick_  
-
-Step 2: use [OfflineInsiderEnroll](https://github.com/abbodi1406/offlineinsiderenroll) to subscribe to the channel you want  
-_while on 10, use BETA for Windows 11 22000.x builds (release), DEV for Windows 11 225xx.x builds (experimental)_  
-
-Step 3: check for updates via Settings - Windows Update and select Upgrade to Windows 11  
-
-Already have a 11 ISO, USB or extracted Files and want to add a bypass  
-----------------------------------------------------------------------  
-Use [Quick_11_iso_esd_wim_TPM_toggle.bat](bypass11/Quick_11_iso_esd_wim_TPM_toggle.bat) from the confort of right-click - SendTo menu  
-
-Switches installation type to Server skipping install checks, or back to Client if run again on the same file, restoring hash!  
-**directly** on any downloaded windows 11 iso or extracted esd and wim, so there's no iso / dism mounting  
-_defiantly quick_  
-
-Works great with business / enterprise media since it comes with ei.cfg so setup won't ask for product key at start  
-for consumer / core media you can add a generic `EI.cfg` to the media\sources yourself with this content:  
-`[Channel]`  
-`_Default`  
-
-> if setup still asks for product key, input retail or gvlk keys found in media\sources\product.ini  
-> _gvlkprofessional=W269N-WFGWX-YVC9B-4J6C9-T83GX gvlkcore=TX9XD-98N7V-6WMQ6-BX7FG-H8Q99_  
-> _gvlkenterprise=NPPR9-FWDCX-D2C8J-H872K-2YT43 gvlkeducation=NW6C2-QMPVW-D7KKK-3GKT6-VCFB2 etc._  
-
-Note that [Skip_TPM_Check_on_Dynamic_Update.cmd](bypass11/Skip_TPM_Check_on_Dynamic_Update.cmd) **will work for manual upgrade as well**  
-_regardless of mounted iso / usb media already having a bypass added or not_  
-
-If having update issues - on any windows version  
-------------------------------------------------  
-Use [windows_update_refresh.bat](bypass11/windows_update_refresh.bat)  
-_AveYo: as a bonus, it hides unsupported PC nags_  
+> The script also picks up any `$ISO$` folder in the current location - for $OEM$ branding, configuration, tweaks etc.  
 
 Changelog  
 ---------  
@@ -160,4 +120,9 @@ _We did it! We broke [the previous gist](https://git.io/MediaCreationTool.bat)_
 2021.12.07: skip windows 11 upgrade checks only via auto.cmd - just ignore server label, please
 2021.12.15: fix regression with 1507-1709 not getting the correct fallback esd; fix dev '-noe' not autoclosing script
 2021.12.22: improved auto.cmd handling of mismatched OS and target edition, obey 'def', 'auto' upgrades 7 to 10, not 11
+2022.03.16: prevent launch errors when run from non-canonical paths; USBLayout progress; pickup $ISO$ dir to add on media
+            DU in 11: auto installs 22000.556 atm; older skip_11_checks, without Server label; Home offline local account
+2022.03.18: fix regression with Auto Upgrade; removed powershell -nop arg (issue #41); enhanced 11 AutoUnattend.xml
+2022.03.20: stable - all issues ironed out; improved script ui; upgrade keeping files from Eval editions too
+            last squash I promise ;)
 ```

+ 55 - 0
bypass11/AutoUnattend.xml

@@ -0,0 +1,55 @@
+<unattend xmlns="urn:schemas-microsoft-com:unattend">
+  <settings pass="windowsPE"><component name="Microsoft-Windows-Setup" processorArchitecture="amd64" language="neutral"
+   xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
+    <UserData><ProductKey><Key>AAAAA-VVVVV-EEEEE-YYYYY-OOOOO</Key><WillShowUI>OnError</WillShowUI></ProductKey></UserData>
+    <ComplianceCheck><DisplayReport>Never</DisplayReport></ComplianceCheck><Diagnostics><OptIn>false</OptIn></Diagnostics>
+    <DynamicUpdate><Enable>true</Enable><WillShowUI>Never</WillShowUI></DynamicUpdate><EnableNetwork>true</EnableNetwork>
+    <RunSynchronous>
+      <!-- Skip 11 Checks on Boot via reg - unreliable vs winsetup.dll patch used in MediaCreationTool.bat -->
+      <RunSynchronousCommand wcm:action="add"><Order>1</Order>
+        <Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassTPMCheck /d 1 /t reg_dword /f</Path></RunSynchronousCommand>
+      <RunSynchronousCommand wcm:action="add"><Order>2</Order>
+        <Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassSecureBootCheck /d 1 /t reg_dword /f</Path></RunSynchronousCommand>
+      <RunSynchronousCommand wcm:action="add"><Order>3</Order>
+        <Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassRAMCheck /d 1 /t reg_dword /f</Path></RunSynchronousCommand>
+      <RunSynchronousCommand wcm:action="add"><Order>4</Order>
+        <Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassStorageCheck /d 1 /t reg_dword /f</Path></RunSynchronousCommand>
+      <RunSynchronousCommand wcm:action="add"><Order>5</Order>
+        <Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassCPUCheck /d 1 /t reg_dword /f</Path></RunSynchronousCommand>
+    </RunSynchronous>
+  </component></settings>  
+  <settings pass="specialize"><component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" language="neutral"
+   xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
+    <RunSynchronous>
+      <!-- offline local account via OOBE\BYPASSNRO on every site but literally no one credits AveYo for sharing it -->
+      <RunSynchronousCommand wcm:action="add"><Order>1</Order>
+        <Path>reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE /v BypassNRO /t reg_dword /d 1 /f</Path>
+      </RunSynchronousCommand>
+      <!-- hide unsupported nag on update settings - 25H1 is not a typo ;) -->
+      <RunSynchronousCommand wcm:action="add"><Order>2</Order>
+        <Path>reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v TargetReleaseVersion /d 1 /t reg_dword /f</Path>
+      </RunSynchronousCommand>
+      <RunSynchronousCommand wcm:action="add"><Order>3</Order>
+        <Path>reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v TargetReleaseVersionInfo /d 25H1 /f</Path>
+      </RunSynchronousCommand>
+    </RunSynchronous>
+  </component></settings>
+  <settings pass="oobeSystem"><component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" language="neutral" 
+   xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
+    <OOBE>
+      <HideLocalAccountScreen>false</HideLocalAccountScreen><HideOnlineAccountScreens>false</HideOnlineAccountScreens>
+      <HideWirelessSetupInOOBE>false</HideWirelessSetupInOOBE><ProtectYourPC>3</ProtectYourPC>
+    </OOBE>  
+    <FirstLogonCommands>
+      <!-- hide unsupported nag on desktop - originally shared by awuctl @ MDL -->
+      <SynchronousCommand wcm:action="add"><Order>1</Order>
+        <CommandLine>reg add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v SV1 /d 0 /t reg_dword /f</CommandLine>
+      </SynchronousCommand><SynchronousCommand wcm:action="add"><Order>2</Order>
+        <CommandLine>reg add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v SV2 /d 0 /t reg_dword /f</CommandLine>
+      </SynchronousCommand>
+    </FirstLogonCommands>
+  </component></settings>
+</unattend>

+ 10 - 3
bypass11/Quick_11_iso_esd_wim_TPM_toggle.bat

@@ -1,13 +1,20 @@
 @(echo off% <#%) &color 07 &title Quick 11 iso esd wim TPM toggle by AveYo - with SendTo menu entry
 set "0=%~f0" &set "1=%~f1"&set "2=%~2"& powershell -nop -c iex ([io.file]::ReadAllText($env:0)) &pause &exit/b ||#>)[1]
 
-#:: what's new in v1.1: fixed relative seek, should now work on all iso's 
+#:: what's new in v1.2: add uninstall when run again without parameters (issue #96) 
 $timer = $(get-date)
 
 #:: Install to SendTo menu when run from another location
-if (!$env:1) { write-host "`n No input iso / esd / wim file to patch! use 'Send to' context menu ...`n" -fore Yellow }
 $SendTo = [Environment]::GetFolderPath('ApplicationData') + '\Microsoft\Windows\SendTo'
-if (!$env:1 -and $env:0 -and $(Split-Path $env:0) -ne $SendTo) {copy $env:0 "$SendTo\Quick_11_iso_esd_wim_TPM_toggle.bat" -force}
+$Script = "$SendTo\Quick_11_iso_esd_wim_TPM_toggle.bat"
+if (!$env:1 -and $env:0 -and !(test-path $Script)) { 
+  write-host "`n No input iso / esd / wim file to patch! use 'Send to' context menu ...`n" -fore Yellow
+  copy $env:0 $Script -force
+}
+elseif (!$env:1 -and $env:0 -and (test-path $Script)) {
+  write-host "`n Removed 'Send to' entry - run again to install ...`n" -fore Magenta
+  del $Script -force
+}
 if (!$env:1) { return }
 
 #:: Can force either patch or undo via second commandline parameter: 1 to patch 0 to undo

+ 150 - 0
bypass11/auto.cmd

@@ -0,0 +1,150 @@
+@echo off& title Auto Upgrade - MCT ||  supports Ultimate / PosReady / Embedded / LTSC / Enterprise Eval
+set "EDITION_SWITCH="
+set "SKIP_11_SETUP_CHECKS=1"
+set OPTIONS=/SelfHost /Auto Upgrade /MigChoice Upgrade /Compat IgnoreWarning /MigrateDrivers All /ResizeRecoveryPartition Disable
+set OPTIONS=%OPTIONS% /ShowOOBE None /Telemetry Disable /CompactOS Disable /DynamicUpdate Enable /SkipSummary /Eula Accept
+
+pushd "%~dp0" & for %%w in (%1) do pushd %%w
+for %%i in ("x86\" "x64\" "") do if exist "%%~isources\setupprep.exe" set "dir=%%~i"
+pushd "%dir%sources" || (echo "%dir%sources" not found! script should be run from windows setup media & timeout /t 5 & exit /b)
+
+::# start sources\setup if under winpe (when booted from media) [Shift] + [F10]: c:\auto or d:\auto or e:\auto etc.
+reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\WinPE">nul 2>nul && (
+ for %%s in (sCPU sRAM sSecureBoot sStorage sTPM) do reg add HKLM\SYSTEM\Setup\LabConfig /f /v Bypas%%sCheck /d 1 /t reg_dword
+ start "WinPE" sources\setup.exe & exit /b 
+) 
+
+::# init variables
+setlocal EnableDelayedExpansion
+set "PATH=%SystemRoot%\System32;%SystemRoot%\System32\windowspowershell\v1.0\;%PATH%"
+set "PATH=%SystemRoot%\Sysnative;%SystemRoot%\Sysnative\windowspowershell\v1.0\;%PATH%"
+
+::# elevate so that workarounds can be set under windows
+fltmc >nul || (set _="%~f0" %*& powershell -nop -c start -verb runas cmd \"/d /x /c call $env:_\"& exit /b)
+
+::# undo any previous regedit edition rename (if upgrade was interrupted)
+set "NT=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
+for %%v in (CompositionEditionID EditionID ProductName) do (
+ call :reg_query "%NT%" %%v_undo %%v
+ if defined %%v reg delete "%NT%" /v %%v_undo /f & for %%A in (32 64) do reg add "%NT%" /v %%v /d "!%%v!" /f /reg:%%A 
+) >nul 2>nul
+
+::# get current version
+for %%v in (CompositionEditionID EditionID ProductName CurrentBuildNumber) do call :reg_query "%NT%" %%v %%v
+for /f "tokens=2-3 delims=[." %%i in ('ver') do for %%s in (%%i) do set /a Version=%%s*10+%%j
+
+::# WIM_INFO w_5=wim_5th b_5=build_5th p_5=patch_5th a_5=arch_5th l_5=lang_5th e_5=edi_5th d_5=desc_5th i_5=edi_5th i_Core=index
+set "0=%~f0"& set wim=& set ext=.esd& if exist install.wim (set ext=.wim) else if exist install.swm set ext=.swm
+set snippet=powershell -nop -c iex ([io.file]::ReadAllText($env:0)-split'#[:]wim_info[:]')[1]; WIM_INFO install%ext% 0 0  
+set w_count=0& for /f "tokens=1-7 delims=," %%i in ('"%snippet%"') do (set w_%%i=%%i,%%j,%%k,%%l,%%m,%%n,%%o& set /a w_count+=1
+set b_%%i=%%j& set p_%%i=%%k& set a_%%i=%%l& set l_%%i=%%m& set e_%%i=%%n& set d_%%i=%%o& set i_%%n=%%i& set i_%%i=%%n)
+
+::# print available editions in install.esd via wim_info snippet
+echo;------------------------------------------------------------------------------------
+for /l %%i in (1,1,%w_count%) do call echo;%%w_%%i%%
+echo;------------------------------------------------------------------------------------
+
+::# get requested edition in EI.cfg or PID.txt or OPTIONS
+if exist product.ini for /f "tokens=1,2 delims==" %%O in (product.ini) do if not "%%P" equ "" (set pid_%%O=%%P& set pn_%%P=%%O)
+set EI=& set Name=& set eID=& set reg=& set "cfg_filter=EditionID Channel OEM Retail Volume _Default VL 0 1 ^$"
+if exist EI.cfg for /f "tokens=*" %%i in ('findstr /v /i /r "%cfg_filter%" EI.cfg') do (set EI=%%i& set eID=%%i)
+if exist PID.txt for /f "delims=;" %%i in (PID.txt) do set %%i 2>nul
+if not defined Value for %%s in (%OPTIONS%) do if defined pn_%%s (set Name=!pn_%%s!& set Name=!Name:gvlk=!)
+if defined Value if not defined Name for %%s in (%Value%) do (set Name=!pn_%%s!& set Name=!Name:gvlk=!)
+if defined EDITION_SWITCH (set eID=%EDITION_SWITCH%) else if defined Name for %%s in (%Name%) do (set eID=%Name%)
+if not defined eID set eID=%EditionID%& if not defined EditionID set eID=Professional& set EditionID=Professional
+if /i "%EditionID%" equ "%eID%" (set changed=) else set changed=1
+
+::# upgrade matrix - now also for Enterprise Eval - automatically pick edition that would keep files and apps
+if /i CoreCountrySpecific equ %eID% set "comp=!eID!" & set "reg=!eID!" & if not defined i_!eID! set "eID=Core"
+if /i CoreSingleLanguage  equ %eID% set "comp=Core"  & set "reg=!eID!" & if not defined i_!eID! set "eID=Core"
+for %%e in (Starter HomeBasic HomePremium CoreConnectedCountrySpecific CoreConnectedSingleLanguage CoreConnected Core) do (
+ if /i %%e  equ %eID% set "comp=Core"  & set "eID=Core"
+ if /i %%eN equ %eID% set "comp=CoreN" & set "eID=CoreN"
+ if /i %%e  equ %eID% if not defined i_Core  set "eID=Professional"  & if not defined reg set "reg=Core"
+ if /i %%eN equ %eID% if not defined i_CoreN set "eID=ProfessionalN" & if not defined reg set "reg=CoreN"
+)
+for %%e in (Ultimate ProfessionalStudent ProfessionalCountrySpecific ProfessionalSingleLanguage) do (
+  if /i %%e equ %eID% (set "eID=Professional") else if /i %%eN equ %eID% set "eID=ProfessionalN"
+)
+for %%e in (EnterpriseG EnterpriseS IoTEnterpriseS IoTEnterprise Embedded) do (
+  if /i %%e equ %eID% (set "eID=Enterprise") else if /i %%eN equ %eID% set "eID=EnterpriseN"
+)
+for %%e in (Enterprise EnterpriseS) do (
+  if /i %%eEval equ %eID% (set "eID=Enterprise") else if /i %%eNEval equ %eID% set "eID=EnterpriseN"
+)
+if /i Enterprise  equ %eID% set "comp=!eID!" & if not defined i_!eID! set "eID=Professional"  & set "reg=!comp!"
+if /i EnterpriseN equ %eID% set "comp=!eID!" & if not defined i_!eID! set "eID=ProfessionalN" & set "reg=!comp!"
+for %%e in (Education ProfessionalEducation ProfessionalWorkstation Professional Cloud) do (
+  if /i %%eN equ %eID% set "comp=EnterpriseN"  & if not defined reg set "reg=%%eN"
+  if /i %%e  equ %eID% set "comp=Enterprise"   & if not defined reg set "reg=%%e"
+  if /i %%eN equ %eID% set "eID=ProfessionalN" & if defined i_%%eN  set "eID=%%eN"
+  if /i %%e  equ %eID% set "eID=Professional"  & if defined i_%%e   set "eID=%%e"
+)
+set index=& set lst=Professional& for /l %%i in (1,1,%w_count%) do if /i !i_%%i! equ !eID! set "index=%%i" & set "eID=!i_%%i!" 
+if not defined index set index=1& set eID=!i_1!& if defined i_%lst% set "index=!i_%lst%!" & set "eID=%lst%"& set "comp=Enterprise"
+set Build=!b_%index%!& set OPTIONS=%OPTIONS% /ImageIndex %index%& if defined changed if not defined reg set "reg=!eID!"
+echo;Current edition: %EditionID% & echo;Regedit edition: %reg% & echo;Index: %index%  Image: %eID%
+timeout /t 10
+
+::# disable upgrade blocks
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f /v DisableWUfBSafeguards /d 1 /t reg_dword >nul 2>nul  
+
+::# prevent usage of MCT for intermediary upgrade in Dynamic Update (causing 7 to 19H1 instead of 7 to 21H2 for example) 
+if "%Build%" gtr "15063" (set OPTIONS=%OPTIONS% /UpdateMedia Decline)
+
+::# skip windows 11 upgrade checks: add launch option trick if old-style 0-byte file trick is not on the media  
+if "%Build%" lss "22000" set /a SKIP_11_SETUP_CHECKS=0
+reg add HKLM\SYSTEM\Setup\MoSetup /f /v AllowUpgradesWithUnsupportedTPMorCPU /d 1 /t reg_dword >nul 2>nul &rem ::# TPM 1.2+ only
+if "%SKIP_11_SETUP_CHECKS%" equ "1" cd.>appraiserres.dll 2>nul & rem ::# writable media only
+for %%A in (appraiserres.dll) do if %%~zA gtr 0 (set TRICK=/Product Server ) else (set TRICK=)
+if "%SKIP_11_SETUP_CHECKS%" equ "1" (set OPTIONS=%TRICK%%OPTIONS%)
+
+::# auto upgrade with edition lie workaround to keep files and apps - all 1904x builds allow up/downgrade between them
+if defined reg call :rename %reg%
+start "auto" setupprep.exe %OPTIONS%
+echo;DONE
+
+EXIT /b
+
+:rename EditionID
+set "NT=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
+for %%v in (CompositionEditionID EditionID ProductName) do reg add "%NT%" /v %%v_undo /d "!%%v!" /f >nul 2>nul
+for %%A in (32 64) do ( 
+ reg add "%NT%" /v CompositionEditionID /d "%comp%" /f /reg:%%A
+ reg add "%NT%" /v EditionID /d "%~1" /f /reg:%%A
+ reg add "%NT%" /v ProductName /d "%~1" /f /reg:%%A
+) >nul 2>nul
+exit /b
+
+:reg_query [USAGE] call :reg_query "HKCU\Volatile Environment" Value variable
+(for /f "tokens=2*" %%R in ('reg query "%~1" /v "%~2" /se "|" %4 2^>nul') do set "%~3=%%S") & exit /b
+
+#:WIM_INFO:# [PARAMS]: "file" [optional]Index or 0 = all  Output 0 = txt 1 = xml 2 = file.txt 3 = file.xml 4 = xml object
+set ^ #=;$f0=[io.file]::ReadAllText($env:0); $0=($f0-split '#[:]WIM_INFO[:]' ,3)[1]; $1=$env:1-replace'([`@$])','`$1'; iex($0+$1)
+set ^ #=& set "0=%~f0"& set 1=;WIM_INFO %*& powershell -nop -c "%#%"& exit /b %errorcode%
+function WIM_INFO ($file = 'install.esd', $index = 0, $out = 0) { :info while ($true) {
+  $block = 2097152; $bytes = new-object 'Byte[]' ($block); $begin = [uint64]0; $final = [uint64]0; $limit = [uint64]0
+  $steps = [int]([uint64]([IO.FileInfo]$file).Length / $block - 1); $enc = [Text.Encoding]::GetEncoding(28591); $delim = @()
+  foreach ($d in '/INSTALLATIONTYPE','/WIM') {$delim += $enc.GetString([Text.Encoding]::Unicode.GetBytes([char]60+ $d +[char]62))}
+  $f = new-object IO.FileStream ($file, 3, 1, 1); $p = 0; $p = $f.Seek(0, 2)
+  for ($o = 1; $o -le $steps; $o++) { 
+    $p = $f.Seek(-$block, 1); $r = $f.Read($bytes, 0, $block); if ($r -ne $block) {write-host invalid block $r; break}
+    $u = [Text.Encoding]::GetEncoding(28591).GetString($bytes); $t = $u.LastIndexOf($delim[0], [StringComparison]::Ordinal) 
+    if ($t -lt 0) { $p = $f.Seek(-$block, 1)} else { [void]$f.Seek(($t -$block), 1)
+      for ($o = 1; $o -le $block; $o++) { [void]$f.Seek(-2, 1); if ($f.ReadByte() -eq 0xfe) {$begin = $f.Position; break} }
+      $limit = $f.Length - $begin; if ($limit -lt $block) {$x = $limit} else {$x = $block}
+      $bytes = new-object 'Byte[]' ($x); $r = $f.Read($bytes, 0, $x) 
+      $u = [Text.Encoding]::GetEncoding(28591).GetString($bytes); $t = $u.IndexOf($delim[1], [StringComparison]::Ordinal)
+      if ($t -ge 0) {[void]$f.Seek(($t + 12 -$x), 1); $final = $f.Position} ; break } }
+  if ($begin -gt 0 -and $final -gt $begin) {
+    $x = $final - $begin; [void]$f.Seek(-$x, 1); $bytes = new-object 'Byte[]' ($x); $r = $f.Read($bytes, 0, $x)
+    if ($r -ne $x) {$f.Dispose(); break} else {[xml]$xml = [Text.Encoding]::Unicode.GetString($bytes); $f.Dispose()}
+  } else {$f.Dispose()} ; break :info }
+  if ($out -eq 1) {[console]::OutputEncoding=[Text.Encoding]::UTF8; $xml.Save([Console]::Out); ''; return} 
+  if ($out -eq 3) {try{$xml.Save(($file-replace'esd$','xml'))}catch{}; return}; if ($out -eq 4) {return $xml}
+  $txt = ''; foreach ($i in $xml.WIM.IMAGE) {if ($index -gt 0 -and $($i.INDEX) -ne $index) {continue}; [int]$a='1'+$i.WINDOWS.ARCH
+  $txt+= $i.INDEX+','+$i.WINDOWS.VERSION.BUILD+','+$i.WINDOWS.VERSION.SPBUILD+','+$(@{10='x86';15='arm';19='x64';112='arm64'}[$a])
+  $txt+= ','+$i.WINDOWS.LANGUAGES.LANGUAGE+','+$i.WINDOWS.EDITIONID+','+$i.NAME+[char]13+[char]10}; $txt=$txt-replace',(?=,)',', '
+  if ($out -eq 2) {try{[io.file]::WriteAllText(($file-replace'esd$','txt'),$txt)}catch{}; return}; if ($out -eq 0) {return $txt}
+} #:WIM_INFO:# Quick WIM SWM ESD ISO info v2 - lean and mean snippet by AveYo, 2021

+ 54 - 1
bypass11/readme.md

@@ -1,4 +1,57 @@
+Windows 11 and the TPM / SecureBoot / CPU / Storage setup checks  
+----------------------------------------------------------------  
+[MediaCreationTool.bat](../MediaCreationTool.bat) creates 11 media that will **automatically skip clean install checks**  
+***Auto Upgrade*** preset, or launching `auto.cmd` from the created media will **automatically skip upgrade checks**  
+Running `setup.exe` from the created media is not guaranteed to bypass setup checks (it should for now)  
+To NOT add bypass to the media, use ***MCT Defaults*** preset or rename the script as `def MediaCreationTool.bat`  
+
+> Regarding the bypass method, for a more reliable and future-proof experience,  
+> clean installation is still handled via _winsetup.dll_ patching in _boot.wim_  
+> upgrade is now handled ~~only~~ via `auto.cmd` with the */Product Server* trick  
+> *Just ignore the 'Windows Server' label, please!*  
+> NEWS: temporarily added back my old-style 0-byte bypass as it still works on release  
+
+i: [Skip_TPM_Check_on_Dynamic_Update.cmd](Skip_TPM_Check_on_Dynamic_Update.cmd) acts globally and **skips setup.exe upgrade checks as well**  
+
+Get 11 via Windows Update on "unsupported" hardware  
+---------------------------------------------------  
+Step 1: use [Skip_TPM_Check_on_Dynamic_Update.cmd](Skip_TPM_Check_on_Dynamic_Update.cmd) to automatically bypass setup requirements  
+_It's a set it and forget it script, with built-in undo - v7 using more reliable /Product Server trick_  
+
+Step 2: use [OfflineInsiderEnroll](https://github.com/abbodi1406/offlineinsiderenroll) to subscribe to the channel you want  
+_while on 10, use BETA for Windows 11 22000.x builds (release), DEV for Windows 11 225xx.x builds (experimental)_  
+
+Step 3: check for updates via Settings - Windows Update and select Upgrade to Windows 11  
+
+Already have a 11 ISO, USB or extracted Files and want to add a bypass  
+----------------------------------------------------------------------  
+Use [Quick_11_iso_esd_wim_TPM_toggle.bat](Quick_11_iso_esd_wim_TPM_toggle.bat) from the confort of right-click - SendTo menu  
+
+Switches installation type to Server skipping install checks, or back to Client if run again on the same file, restoring hash!  
+**directly** on any downloaded windows 11 iso or extracted esd and wim, so there's no iso / dism mounting  
+_defiantly quick_  
+
+Works great with business / enterprise media since it comes with ei.cfg so setup won't ask for product key at start  
+for consumer / core media you can add a generic `EI.cfg` to the media\sources yourself with this content:  
+`[Channel]`  
+`_Default`  
+
+> if setup still asks for product key, input retail or gvlk keys found in media\sources\product.ini  
+> _gvlkprofessional=W269N-WFGWX-YVC9B-4J6C9-T83GX gvlkcore=TX9XD-98N7V-6WMQ6-BX7FG-H8Q99_  
+> _gvlkenterprise=NPPR9-FWDCX-D2C8J-H872K-2YT43 gvlkeducation=NW6C2-QMPVW-D7KKK-3GKT6-VCFB2 etc._  
+
+i: [Skip_TPM_Check_on_Dynamic_Update.cmd](Skip_TPM_Check_on_Dynamic_Update.cmd) acts globally and **skips setup.exe upgrade checks as well**  
+_regardless of mounted iso / usb media already having a bypass added or not_  
+
+Offline local account on 11 Home / Pro  
+--------------------------------------  
+[MediaCreationTool.bat](../MediaCreationTool.bat) creates media that re-enables the *I dont have internet* OOBE choice (OOBE\BypassNRO)  
+It does so via [AutoUnattend.xml](AutoUnattend.xml), inserted into `boot.wim` to not cause setup.exe issues under windows  
+More conveniently can be placed at the root of 11 media, along with [auto.cmd](auto.cmd) to use for upgrades  
+Should work with any 11 Release (22000.x) or Dev (22xxx.x) media - and it hides unsupported PC nags as a bonus ;)  
+_If you have already connected at OOBE, can try email: `a` or `[email protected]` password: `a` or `test` to switch to local account_  
+
 If having update issues - on any windows version  
 ------------------------------------------------  
-Use [windows_update_refresh.bat](bypass11/windows_update_refresh.bat)  
+Use [windows_update_refresh.bat](windows_update_refresh.bat)  
 _AveYo: as a bonus, it hides unsupported PC nags_  

+ 6 - 5
bypass11/windows_update_refresh.bat

@@ -12,17 +12,18 @@ $_Paste_in_Powershell = {
     kill -name $_ -force -ea 0
   }
   cmd /c rd /s /q "%SystemDrive%\`$WINDOWS.~BT\Sources\Panther"
-  cmd /c rd /s /q "%SystemRoot%\system32\catroot2"
+  cmd /c rd /s /q "%SystemRoot%\system32\catroot2" # because kill $svc.PID ;)
   cmd /c rd /s /q "%SystemRoot%\SoftwareDistribution"
   cmd /c del /f /q "%SystemRoot%\Logs\WindowsUpdate\*"
-  cmd /c del /f /q "%ProgramData%\USOPrivate\UpdateStore\*"
+  cmd /c del /f /q "%ProgramData%\USOPrivate\UpdateStore\*" # clearing USO suggested by abbodi1406 @ MDL
   cmd /c del /s /f /q "%ProgramData%\USOShared\Logs\*"
   cmd /c rd /s /q "%ProgramFiles%\UNP"
   try { Get-WindowsUpdateLog -LogPath $env:temp\temp.log -ForceFlush -Confirm:$False -ea 0 } catch {}
-  <# AveYo: comment 3 lines below to NOT hide 11 unsupported/upgrade nag - 25H1 is NOT a typo #>
-  reg add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /d 0 /t reg_dword /f
+  <# AveYo: comment reg lines below to NOT hide 11 unsupported/upgrade nag #>
+  reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /v "TargetReleaseVersionInfo" /d 25H1 /f # 25H1 NOT a typo ;)
   reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /v "TargetReleaseVersion" /d 1 /t reg_dword /f
-  reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /v "TargetReleaseVersionInfo" /d 25H1 /f
+  reg add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /d 0 /t reg_dword /f # hide desktop watermark
+  reg add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v "SV1" /d 0 /t reg_dword /f # suggested by awuctl @ MDL
   net1 start wuauserv; net1 start bits; net1 start usosvc
   UsoClient RefreshSettings
   sleep 5