diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore index 8250ba0..6b2d97e 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,8 @@ $RECYCLE.BIN/ *.Package.ps1 CustomMenu.inf *.zip -ChangeLog_Full.md \ No newline at end of file +ChangeLog_Full.md +/Optimize-Offline_* +/OfflineTemp* +/Src/GUI/image_info.json +/ConsoleOut.txt diff --git a/ChangeLog.md b/ChangeLog.md index e81961b..fd4a21b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,32 @@ # ChangeLog # +## Build 4.0.1.10 (02-16-2023) ## + +- Corrected the improper formatting of the output WimFileInfo.xml file when running Optimize-Offline with PowerShell 7+ +- Windows 10 22H2 will now display properly in the output WimFileInfo.xml file. +- Added additional telemetry disabling registry entries. +- Disabled Interests and News and Meet Now taskbar registry entries. +- Updated the Win32Calc integration WIM file. +- Updated the integrated Microsoft Edge Administrative Policy Templates WIM file to the latest versions. +- Updated the integrated CustomAppsAssociations.xml +- Updated the 'Additional Tweaks' registry template. +- Updated the Set-Additional.ps1 post-setup script. +- Added a Remove-DefaultUser0.ps1 post-setup script. +- The Get-DeploymentTool function has been replaced with the Get-DISMPath function. +- Removed redundancies in the Invoke-Cleanup function. +- Additional framework code changes and other core module updates. + +**NOTE: Windows 11 compatibility will be coming with build 4.0.2. Furthermore, the reason for the fairly long hiatus with updates has been due to the passing of my father and the subsequent birth of a little bundle of joy. Though my personal life is not anyone's business on the internet, I also do not think it's fair to let those who use this framework to sit in the dark about its current state. Conclusively, I will try to get to the Troubleshooting/Bug reports as soon as I'm available to do so. Thank you for your understanding and patience.** + +## Build 4.0.1.9 (09-12-2021) ## + +- Optimize-Offline's native ISO creation function has been re-written and now supports PowerShell 6+. +- The names of the Biometric FOD packages that are automatically removed when the BioEnrollment System Application has been removed are now displayed and logged. +- Added the disabling of Windows Taskbar Interests and News. +- Additional framework code changes and other core module updates. + +**NOTE: A very small update was added on 09-16-2021 that adds 21H2 to the Get-ImageData function as well as the module manifest.** + ## Build 4.0.1.8 (06-22-2021) ## **NOTE: Updates should resume with the same frequency as before.** @@ -37,19 +64,3 @@ - Updated the Windows Store bundle packages. - The MAML XML external help file and manifest data have been updated. - Multiple code improvements across the framework. - -## Build 4.0.1.5 (09-17-2020) ## - -- Fixed an error where the metadata for the image would not be returned if both the -DaRT and -Additional parameters were omitted. -- Updated the Win32Calc integration image package to correct a bug where selecting 'Unit Conversion' from its drop-down list would cause the Win32Calc.exe to close immediately. -- Updated the Resource Function that returns the metadata for any images being optimized. -- Additional Optimize-Offline code improvements. - -## Build 4.0.1.4 (08-23-2020) ## - -- Added support for Windows 10 build 19042 (20H2). -- Added the new 20H2 Start Menu Experience to the applied registry settings. -- Corrected an issue for Windows 10 builds 19041+ where it occasionally would be returned as an unsupported image build. -- Updated the Windows Store bundle packages. -- Updated the optional Set-Additional runtime script. -- Multiple code improvements across the framework. diff --git a/Configuration.json b/Configuration.json index d5ca3aa..d21d528 100644 --- a/Configuration.json +++ b/Configuration.json @@ -1,36 +1,61 @@ { - "_Info": [ - "This is a JSON based Configuration file for Optimize-Offline.", - "Ensure proper formatting is used when editing the JSON parameter values.", - "Boolean parameter values use true and false. String parameter values must be enclosed in double-quotes." - ], - "SourcePath": "Path:\\To\\SourceImage", - "WindowsApps": "Select", - "SystemApps": true, - "Capabilities": true, - "Packages": false, - "Features": true, - "DeveloperMode": false, - "WindowsStore": false, - "MicrosoftEdge": false, - "Win32Calc": true, - "Dedup": true, - "DaRT": [ - "Setup", - "Recovery" - ], - "Registry": true, - "Additional": { - "Setup": false, - "Wallpaper": false, - "SystemLogo": false, - "LockScreen": false, - "RegistryTemplates": false, - "LayoutModification": false, - "Unattend": false, - "Drivers": false, - "NetFx3": false - }, - "ComponentCleanup": false, - "ISO": "No-Prompt" + "_Info": [ + "This is a JSON based Configuration file for Optimize-Offline.", + "Ensure proper formatting is used when editing the JSON parameter values.", + "Boolean parameter values use true and false. String parameter values must be enclosed in double-quotes.", + "WindowsApps, SystemApps, Capabilities, Packages : All | None | Select | Whitelist | Blacklist", + "FeaturesToEnable, FeaturesToDisable : All | None | Select | List", + "Services : None | Select | List | Advanced", + "CompressionType: Select | None | Fast | Maximum | Solid", + "OutputPath : default | path[{filename}?] | select", + "FlashToUSB: Off | UEFI | Legacy" + ], + "SourcePath": "PathTo:\\sources\\install.wim", + "WindowsApps": "Select", + "SystemApps": "Select", + "Capabilities": "None", + "Packages": "None", + "FeaturesToEnable": "List", + "FeaturesToDisable": "List", + "Services": "Select", + "DeveloperMode": false, + "WindowsStore": false, + "MicrosoftEdge": false, + "Win32Calc": false, + "DormantDefender": false, + "Dedup": false, + "DaRT": [], + "Registry": false, + "OutputPath": "default", + "Additional": { + "Setup": false, + "Wallpaper": false, + "SystemLogo": false, + "LockScreen": false, + "RegistryTemplates": false, + "LayoutModification": false, + "Unattend": false, + "Drivers": false, + "NetFx3": false + }, + "ComponentCleanup": false, + "ISO": "No-Prompt", + "CompressionType": "Maximum", + "SelectiveRegistry": { + "DisableWindowsUpgrade": false, + "DisableWindowsUpdateMicrosoft": false, + "DisableDriverUpdate": false, + "DormantOneDrive": false, + "Disable3rdPartyApps": false, + "W11ClassicContextMenu": false, + "ExplorerUIRibbon": false, + "ClassicSearchExplorer": false, + "RemoveTaskbarPinnedIcons": false, + "DisableTeamsApp": false, + "DisableVirtualizationSecurity": false, + "RunAsTiContextMenu": false, + "AmoledBlackTheme": false + }, + "ShutDownOnComplete": false, + "FlashToUSB": "Off" } \ No newline at end of file diff --git a/Content/Additional/LayoutModification/README.md b/Content/Additional/LayoutModification/README.md index 2d57b72..c58c859 100644 --- a/Content/Additional/LayoutModification/README.md +++ b/Content/Additional/LayoutModification/README.md @@ -1 +1 @@ -If adding additional user content, place any custom Start Menu layout XML (LayoutModification.xml) file to be added to the image here. +If adding additional user content, place any custom Start Menu layout XML/JSON (LayoutModification.xml/LayoutModification.json) file to be added to the image here. diff --git a/Content/Additional/RegistryTemplates/Additional Tweaks.reg b/Content/Additional/RegistryTemplates/Additional Tweaks.reg index 6d5f09a..fb1761f 100644 Binary files a/Content/Additional/RegistryTemplates/Additional Tweaks.reg and b/Content/Additional/RegistryTemplates/Additional Tweaks.reg differ diff --git a/Content/Additional/SelectiveRegistry/AMOLED_black_theme.reg b/Content/Additional/SelectiveRegistry/AMOLED_black_theme.reg new file mode 100644 index 0000000..9891bd1 --- /dev/null +++ b/Content/Additional/SelectiveRegistry/AMOLED_black_theme.reg @@ -0,0 +1,87 @@ +Windows Registry Editor Version 5.00 + +; Pitch Black Theme preset by AveYo, AccentPalette idea by /u/Egg-Tricky +; for Ctrl+Alt+Del, Logon, Taskbar, Start Menu, Action Center, Title Bar (10 & 11) + +[-HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent] +[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent] +"AccentColorMenu"=dword:1f000000 ; Window borders and titlebar +"StartColorMenu"=dword:1f202020 ; Modals in UWP ex. Apply new refresh rate in 10 +"AccentPalette"=hex:\ + 00,9d,ff,1f,\ ; Links in action center and apps + 00,9d,ff,1f,\ ; Taskbar icons underline + 00,9d,ff,1f,\ ; Start button hover + 00,9d,ff,1f,\ ; Settings icons and links [Blue] + 00,00,00,00,\ ; Startmenu background / Active taskbar button - IF "EnableTransparency"=dword:00000000 + 00,00,00,00,\ ; Taskbar front and Folders on start list background [None] + 00,00,00,00,\ ; Taskbar background - IF "EnableTransparency"=dword:00000001 + 00,00,00,00 ; Unused + +[-HKEY_USERS\.DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent] +[HKEY_USERS\.DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent] +"AccentColorMenu"=dword:1f000000 ; Window borders and titlebar +"StartColorMenu"=dword:1f202020 ; Modals in UWP ex. Apply new refresh rate in 10 +"AccentPalette"=hex:\ + 00,9d,ff,1f,\ ; Links in action center and apps + 00,9d,ff,1f,\ ; Taskbar icons underline + 00,9d,ff,1f,\ ; Start button hover + 00,9d,ff,1f,\ ; Settings icons and links [Blue] + 00,00,00,00,\ ; Startmenu background / Active taskbar button - IF "EnableTransparency"=dword:00000000 + 00,00,00,00,\ ; Taskbar front and Folders on start list background [None] + 00,00,00,00,\ ; Taskbar background - IF "EnableTransparency"=dword:00000001 + 00,00,00,00 ; Unused + +[-HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\DWM] +[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\DWM] +"ColorPrevalence"=dword:00000001 ; Show accent color on Title bars and window borders [x] +"AccentColor"=dword:1f000000 ; Active title bars - black unsupported in the UI but works with AccentPalette +"AccentColorInactive"=dword:1f202020 ; Inactive title bars + +[-HKEY_USERS\.DEFAULT\SOFTWARE\Microsoft\Windows\DWM] +[HKEY_USERS\.DEFAULT\SOFTWARE\Microsoft\Windows\DWM] +"ColorPrevalence"=dword:00000001 ; Show accent color on Title bars and window borders [x] +"AccentColor"=dword:1f000000 ; Active title bars - black unsupported in the UI but works with AccentPalette +"AccentColorInactive"=dword:1f202020 ; Inactive title bars + +[-HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize] +[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize] +"ColorPrevalence"=dword:00000001 ; Show accent color on Start, taskbar and action center [x] +"AppsUseLightTheme"=dword:00000000 ; Apps mode [Dark] +"SystemUsesLightTheme"=dword:00000000 ; Windows mode [Dark] +"EnabledBlurBehind"=dword:00000001 ; Blur [x] +"EnableTransparency"=dword:00000000 ; Transparency [] + +[-HKEY_USERS\.DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize] +[HKEY_USERS\.DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize] +"ColorPrevalence"=dword:00000001 ; Show accent color on Start, taskbar and action center [x] +"AppsUseLightTheme"=dword:00000000 ; Apps mode [Dark] +"SystemUsesLightTheme"=dword:00000000 ; Windows mode [Dark] +"EnabledBlurBehind"=dword:00000001 ; Blur [x] +"EnableTransparency"=dword:00000000 ; Transparency [] + +[-HKEY_CURRENT_USER\Control Panel\Colors] +[HKEY_CURRENT_USER\Control Panel\Colors] +"Hilight"="0 157 255" ; [Blue] +"HotTrackingColor"="0 157 255" +"MenuHilight"="0 157 255" + +[-HKEY_USERS\.DEFAULT\Control Panel\Colors] +[HKEY_USERS\.DEFAULT\Control Panel\Colors] +"Hilight"="0 157 255" ; [Blue] +"HotTrackingColor"="0 157 255" +"MenuHilight"="0 157 255" + +[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon] +"Background"="0 0 0" + +[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\System] +"DisableAcrylicBackgroundOnLogon"=dword:00000001 ; AveYo: enable pure black logon on 11 +"DisableLogonBackgroundImage"=dword:00000001 ; enable solid color logon - separate undo.reg provided + +[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Personalization] +"PersonalColors_Background"="#000000" ; AveYo: this is what was missing to make Ctrl+Alt+Del background black as well +"PersonalColors_Accent"=- +"NoLockScreen"=dword:00000001 ; no lock screen entirely - separate undo.reg provided + +[-HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DWM] +; done - log off and back on to see all changes \ No newline at end of file diff --git a/Content/Additional/SelectiveRegistry/RunAsTi.reg b/Content/Additional/SelectiveRegistry/RunAsTi.reg new file mode 100644 index 0000000..6eb192d --- /dev/null +++ b/Content/Additional/SelectiveRegistry/RunAsTi.reg @@ -0,0 +1,121 @@ +Windows Registry Editor Version 5.00 + +; Context Menu entries to use RunAsTI - lean and mean snippet by AveYo, 2018-2022 +; [FEATURES] +; - innovative HKCU load, no need for reg load / unload ping-pong; programs get the user profile +; - sets ownership privileges, high priority, and explorer support; get System if TI unavailable +; - accepts special characters in paths for which default run as administrator fails +; - show on the new 11 contextmenu via whitelisted id; plenty other available, f**k needing an app! +; 2022.01.28: workaround for 11 release (22000) hindering explorer as TI; fix 7 args + +[-HKEY_CLASSES_ROOT\RunAsTI] +[-HKEY_CLASSES_ROOT\batfile\shell\setdesktopwallpaper] +[-HKEY_CLASSES_ROOT\cmdfile\shell\setdesktopwallpaper] +[-HKEY_CLASSES_ROOT\exefile\shell\setdesktopwallpaper] +[-HKEY_CLASSES_ROOT\mscfile\shell\setdesktopwallpaper] +[-HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\setdesktopwallpaper] +[-HKEY_CLASSES_ROOT\regfile\shell\setdesktopwallpaper] +[-HKEY_CLASSES_ROOT\Folder\shell\setdesktopwallpaper] +[-HKEY_CLASSES_ROOT\Directory\background\shell\extract] +; To remove entries, copy paste above into undo_RunAsTI.reg file, then import it + +; RunAsTI on .bat +[HKEY_CLASSES_ROOT\batfile\shell\setdesktopwallpaper] +"MUIVerb"="Run as trustedinstaller" +"HasLUAShield"="" +"Icon"="powershell.exe,0" +[HKEY_CLASSES_ROOT\batfile\shell\setdesktopwallpaper\command] +@="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -win 1 -nop -c iex((10..39|%%{(gp 'Registry::HKCR\\RunAsTI' $_ -ea 0).$_})-join[char]10); # --%% \"%L\"" + +; RunAsTI on .cmd +[HKEY_CLASSES_ROOT\cmdfile\shell\setdesktopwallpaper] +"MUIVerb"="Run as trustedinstaller" +"HasLUAShield"="" +"Icon"="powershell.exe,0" +[HKEY_CLASSES_ROOT\cmdfile\shell\setdesktopwallpaper\command] +@="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -win 1 -nop -c iex((10..39|%%{(gp 'Registry::HKCR\\RunAsTI' $_ -ea 0).$_})-join[char]10); # --%% \"%L\"" + +; RunAsTI on .exe +[HKEY_CLASSES_ROOT\exefile\shell\setdesktopwallpaper] +"MUIVerb"="Run as trustedinstaller" +"HasLUAShield"="" +"Icon"="powershell.exe,0" +[HKEY_CLASSES_ROOT\exefile\shell\setdesktopwallpaper\command] +@="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -win 1 -nop -c iex((10..39|%%{(gp 'Registry::HKCR\\RunAsTI' $_ -ea 0).$_})-join[char]10); # --%% \"%L\"" + +; RunAsTI on .msc +[HKEY_CLASSES_ROOT\mscfile\shell\setdesktopwallpaper] +"MUIVerb"="Run as trustedinstaller" +"HasLUAShield"="" +"Icon"="powershell.exe,0" +[HKEY_CLASSES_ROOT\mscfile\shell\setdesktopwallpaper\command] +@="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -win 1 -nop -c iex((10..39|%%{(gp 'Registry::HKCR\\RunAsTI' $_ -ea 0).$_})-join[char]10); # --%% \"%L\"" + +; RunAsTI on .ps1 +[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\setdesktopwallpaper] +"MUIVerb"="Run as trustedinstaller" +"HasLUAShield"="" +"Icon"="powershell.exe,0" +[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\setdesktopwallpaper\command] +@="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -win 1 -nop -c iex((10..39|%%{(gp 'Registry::HKCR\\RunAsTI' $_ -ea 0).$_})-join[char]10); # --%% powershell -nop -c iex((gc -lit '%L')-join[char]10)" + +; RunAsTI on .reg +[HKEY_CLASSES_ROOT\regfile\shell\setdesktopwallpaper] +"MUIVerb"="Import as trustedinstaller" +"HasLUAShield"="" +"Icon"="powershell.exe,0" +[HKEY_CLASSES_ROOT\regfile\shell\setdesktopwallpaper\command] +@="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -win 1 -nop -c iex((10..39|%%{(gp 'Registry::HKCR\\RunAsTI' $_ -ea 0).$_})-join[char]10); # --%% regedit /s \"%L\"" + +; RunAsTI on Folder +[HKEY_CLASSES_ROOT\Folder\shell\setdesktopwallpaper] +"MuiVerb"="Open as trustedinstaller" +"HasLUAShield"="" +"Icon"="powershell.exe,0" +"AppliesTo"="NOT System.ParsingName:=\"::{645FF040-5081-101B-9F08-00AA002F954E}\"" +[HKEY_CLASSES_ROOT\Folder\shell\setdesktopwallpaper\command] +@="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -win 1 -nop -c iex((10..39|%%{(gp 'Registry::HKCR\\RunAsTI' $_ -ea 0).$_})-join[char]10); # --%% \"%L\"" + +; Open Powershell as trustedinstaller here +[HKEY_CLASSES_ROOT\Directory\background\shell\extract] +"MuiVerb"="Powershell as trustedinstaller" +"HasLUAShield"="" +"NoWorkingDirectory"="" +"Position"="Middle" +"Icon"="powershell.exe,0" +[HKEY_CLASSES_ROOT\Directory\background\shell\extract\command] +@="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -win 1 -nop -c iex((10..39|%%{(gp 'Registry::HKCR\\RunAsTI' $_ -ea 0).$_})-join[char]10); # --%% cmd /c set \"1=%V\"& start powershell -nop -noe -c $host.ui.RawUI.WindowTitle=$(whoami); set-location -lit $env:1" + +; RunAsTI function +[HKEY_CLASSES_ROOT\RunAsTI] +"10"="function RunAsTI ($cmd,$arg) { $id='RunAsTI'; $key=\"Registry::HKU\\$(((whoami /user)-split' ')[-1])\\Volatile Environment\"; $code=@'" +"11"=" $I=[int32]; $M=$I.module.gettype(\"System.Runtime.Interop`Services.Mar`shal\"); $P=$I.module.gettype(\"System.Int`Ptr\"); $S=[string]" +"12"=" $D=@(); $T=@(); $DM=[AppDomain]::CurrentDomain.\"DefineDynami`cAssembly\"(1,1).\"DefineDynami`cModule\"(1); $Z=[uintptr]::size " +"13"=" 0..5|% {$D += $DM.\"Defin`eType\"(\"AveYo_$_\",1179913,[ValueType])}; $D += [uintptr]; 4..6|% {$D += $D[$_].\"MakeByR`efType\"()}" +"14"=" $F='kernel','advapi','advapi', ($S,$S,$I,$I,$I,$I,$I,$S,$D[7],$D[8]), ([uintptr],$S,$I,$I,$D[9]),([uintptr],$S,$I,$I,[byte[]],$I)" +"15"=" 0..2|% {$9=$D[0].\"DefinePInvok`eMethod\"(('CreateProcess','RegOpenKeyEx','RegSetValueEx')[$_],$F[$_]+'32',8214,1,$S,$F[$_+3],1,4)}" +"16"=" $DF=($P,$I,$P),($I,$I,$I,$I,$P,$D[1]),($I,$S,$S,$S,$I,$I,$I,$I,$I,$I,$I,$I,[int16],[int16],$P,$P,$P,$P),($D[3],$P),($P,$P,$I,$I)" +"17"=" 1..5|% {$k=$_; $n=1; $DF[$_-1]|% {$9=$D[$k].\"Defin`eField\"('f' + $n++, $_, 6)}}; 0..5|% {$T += $D[$_].\"Creat`eType\"()}" +"18"=" 0..5|% {nv \"A$_\" ([Activator]::CreateInstance($T[$_])) -fo}; function F ($1,$2) {$T[0].\"G`etMethod\"($1).invoke(0,$2)}" +"19"=" $TI=(whoami /groups)-like'*1-16-16384*'; $As=0; if(!$cmd) {$cmd='control';$arg='admintools'}; if ($cmd-eq'This PC'){$cmd='file:'}" +"20"=" if (!$TI) {'TrustedInstaller','lsass','winlogon'|% {if (!$As) {$9=sc.exe start $_; $As=@(get-process -name $_ -ea 0|% {$_})[0]}}" +"21"=" function M ($1,$2,$3) {$M.\"G`etMethod\"($1,[type[]]$2).invoke(0,$3)}; $H=@(); $Z,(4*$Z+16)|% {$H += M \"AllocHG`lobal\" $I $_}" +"22"=" M \"WriteInt`Ptr\" ($P,$P) ($H[0],$As.Handle); $A1.f1=131072; $A1.f2=$Z; $A1.f3=$H[0]; $A2.f1=1; $A2.f2=1; $A2.f3=1; $A2.f4=1" +"23"=" $A2.f6=$A1; $A3.f1=10*$Z+32; $A4.f1=$A3; $A4.f2=$H[1]; M \"StructureTo`Ptr\" ($D[2],$P,[boolean]) (($A2 -as $D[2]),$A4.f2,$false)" +"24"=" $Run=@($null, \"powershell -win 1 -nop -c iex `$env:R; # $id\", 0, 0, 0, 0x0E080600, 0, $null, ($A4 -as $T[4]), ($A5 -as $T[5]))" +"25"=" F 'CreateProcess' $Run; return}; $env:R=''; rp $key $id -force; $priv=[diagnostics.process].\"GetM`ember\"('SetPrivilege',42)[0]" +"26"=" 'SeSecurityPrivilege','SeTakeOwnershipPrivilege','SeBackupPrivilege','SeRestorePrivilege' |% {$priv.Invoke($null, @(\"$_\",2))}" +"27"=" $HKU=[uintptr][uint32]2147483651; $NT='S-1-5-18'; $reg=($HKU,$NT,8,2,($HKU -as $D[9])); F 'RegOpenKeyEx' $reg; $LNK=$reg[4]" +"28"=" function L ($1,$2,$3) {sp 'Registry::HKCR\\AppID\\{CDCBCFCA-3CDC-436f-A4E2-0E02075250C2}' 'RunAs' $3 -force -ea 0" +"29"=" $b=[Text.Encoding]::Unicode.GetBytes(\"\\Registry\\User\\$1\"); F 'RegSetValueEx' @($2,'SymbolicLinkValue',0,6,[byte[]]$b,$b.Length)}" +"30"=" function Q {[int](gwmi win32_process -filter 'name=\"explorer.exe\"'|?{$_.getownersid().sid-eq$NT}|select -last 1).ProcessId}" +"31"=" $11bug=($((gwmi Win32_OperatingSystem).BuildNumber)-eq'22000')-AND(($cmd-eq'file:')-OR(test-path -lit $cmd -PathType Container))" +"32"=" if ($11bug) {'System.Windows.Forms','Microsoft.VisualBasic' |% {$9=[Reflection.Assembly]::LoadWithPartialName(\"'$_\")}}" +"33"=" if ($11bug) {$path='^(l)'+$($cmd -replace '([\\+\\^\\%\\~\\(\\)\\[\\]])','{$1}')+'{ENTER}'; $cmd='control.exe'; $arg='admintools'}" +"34"=" L ($key-split'\\\\')[1] $LNK ''; $R=[diagnostics.process]::start($cmd,$arg); if ($R) {$R.PriorityClass='High'; $R.WaitForExit()}" +"35"=" if ($11bug) {$w=0; do {if($w-gt40){break}; sleep -mi 250;$w++} until (Q); [Microsoft.VisualBasic.Interaction]::AppActivate($(Q))}" +"36"=" if ($11bug) {[Windows.Forms.SendKeys]::SendWait($path)}; do {sleep 7} while(Q); L '.Default' $LNK 'Interactive User'" +"37"="'@; $V='';'cmd','arg','id','key'|%{$V+=\"`n`$$_='$($(gv $_ -val)-replace\"'\",\"''\")';\"}; sp $key $id $($V,$code) -type 7 -force -ea 0" +"38"=" start powershell -args \"-win 1 -nop -c `n$V `$env:R=(gi `$key -ea 0).getvalue(`$id)-join''; iex `$env:R\" -verb runas" +"39"="}; $A=([environment]::commandline-split'-[-]%+ ?',2)[1]-split'\"([^\"]+)\"|([^ ]+)',2|%{$_.Trim(' \"')}; RunAsTI $A[1] $A[2]; # AveYo, 2022.01.28" +; diff --git a/Content/Additional/SelectiveRegistry/SelectiveRegistry.ps1 b/Content/Additional/SelectiveRegistry/SelectiveRegistry.ps1 new file mode 100644 index 0000000..0a3621c --- /dev/null +++ b/Content/Additional/SelectiveRegistry/SelectiveRegistry.ps1 @@ -0,0 +1,167 @@ +RegHives -Load +If($SelectiveRegistry.DisableWindowsUpgrade) { + + $TargetReleaseVersionInfo = $null + + Switch ($Global:InstallInfo.Build) { + "17134" { $TargetReleaseVersionInfo = "1803" } + "17763" { $TargetReleaseVersionInfo = "1809" } + "18362" { $TargetReleaseVersionInfo = "1903" } + "18363" { $TargetReleaseVersionInfo = "1909" } + "19041" { $TargetReleaseVersionInfo = "2004" } + "19042" { $TargetReleaseVersionInfo = "2009" } + "19043" { $TargetReleaseVersionInfo = "21H1" } + } + + If ($Global:InstallInfo.Build -ge "19044") { + $TargetReleaseVersionInfo = "21H2" + } + + If ($Global:InstallInfo.Build -ge "22500") { + $TargetReleaseVersionInfo = "22H2" + } + + If ($TargetReleaseVersionInfo){ + + Log $OptimizeData.SelectiveRegistryWindowsUpgrade + + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "AUOptions" -Type DWord -Value "2" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoUpdate" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "DeferUpdatePeriod" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "DeferUpgrade" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "DeferUpgradePeriod" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "TargetReleaseVersion" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "TargetReleaseVersionInfo" -Type String -Value $TargetReleaseVersionInfo + + If ($Global:InstallInfo.Build -ge "17134" -and $Global:InstallInfo.Build -le "20348") { RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "ProductVersion" -Type String -Value "Windows 10" } + + If ($Global:InstallInfo.Build -ge "22000") { RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "ProductVersion" -Type String -Value "Windows 11" } + + } + Start-Sleep 1 +} +If($SelectiveRegistry.DisableWindowsUpdateMicrosoft) { + Log $OptimizeData.SelectiveRegistryWindowsUpdateMS + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "DoNotConnectToWindowsUpdateInternetLocations" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "DisableWindowsUpdateAccess" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "WUServer" -Type String -Value " " + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "WUStatusServer" -Type String -Value " " + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "UpdateServiceUrlAlternate" -Type String -Value " " + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "UseWUServer" -Type DWord -Value "1" + Start-Sleep 1 +} + +If($SelectiveRegistry.DisableDriverUpdate) { + Log $OptimizeData.SelectiveRegistryDriverUpdate + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\Device Metadata" -Name "PreventDeviceMetadataFromNetwork" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DontPromptForWindowsUpdate" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DontSearchWindowsUpdate" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DriverUpdateWizardWuSearchEnabled" -Type DWord -Value "0" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "SearchOrderConfig" -Type DWord -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "ExcludeWUDriversInQualityUpdate" -Type DWord -Value "1" + Start-Sleep 1 +} + +If($SelectiveRegistry.DormantOneDrive) { + Log $OptimizeData.SelectiveRegistryDormantOneDrive + RegKey -Path "HKLM:\WIM_HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" -Name "OneDriveSetup" -Type DWord -Value "0" + Start-Sleep 1 +} + +# classic search in explorer +If($SelectiveRegistry.ClassicSearchExplorer -and $Global:InstallInfo.Build -ge '18363') { + + Log $OptimizeData.SelectiveRegistryClassicSearchExplorer + + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Classes\CLSID\{1d64637d-31e9-4b06-9124-e83fb178ac6e}\TreatAs" -Name "(default)" -Value "{64bc32b5-4eec-4de7-972d-bd8bd0324537}" -Type String -Force + + Start-Sleep 1 +} + +If($SelectiveRegistry.RemoveTaskbarPinnedIcons){ + + Log $OptimizeData.SelectiveRegistryRemoveTaskbarPinnedIcons + + ## Disable taskbar taskview button + RegKey -Path "HKLM:\WIM_HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "ShowTaskViewButton" -Type Dword -Value "0" -Force + + If($Global:InstallInfo.Build -ge '18362') { + #Hide MeetNow icon in taskbar + RegKey -Path "HKLM:\WIM_HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "HideSCAMeetNow" -Type dword -Value "1" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "HideSCAMeetNow" -Type dword -Value "1" + } + + if($Global:InstallInfo.Build -le '19044'){ + RegKey -Path "HKLM:\WIM_HKCU\Software\Policies\Microsoft\Windows\Explorer" -Name "NoPinningStoreToTaskbar" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband\AuxilliaryPins" -Name "MailPin" -Value 2 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People" -Name "PeopleBand" -Value 0 -Type DWord + } + + # Disable News & Interests icon + RegKey -Path "HKLM:\WIM_HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Feeds" -Name "ShellFeedsTaskbarViewMode" -Type dword -Value "2" + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\Windows Feeds" -Name "EnableFeeds" -Type dword -Value "0" + + If($Global:InstallInfo.Build -ge '22000') { + #Remove Chat icon in taskbar + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\Windows Chat" -Name "ChatIcon" -Type dword -Value "3" + RegKey -Path "HKLM:\WIM_HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "TaskbarMn" -Type dword -Value "0" + + ## Disable widgets button + RegKey -Path "HKLM:\WIM_HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "TaskbarDa" -Type Dword -Value "0" -Force + } + + Start-Sleep 1 + +} + +If($SelectiveRegistry.W11ClassicContextMenu -and $Global:InstallInfo.Build -ge '22000') { + Log $OptimizeData.SelectiveRegistryW11ClassicContextMenu + # Classic context menus + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" -Name "(default)" -Value "" -Type String -Force + Start-Sleep 1 +} + +if($SelectiveRegistry.DisableTeamsApp -and $Global:InstallInfo.Build -ge '10240') { + Log $OptimizeData.SelectiveRegistryDisableTeamsApp + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\Communications" -Name "ConfigureChatAutoInstall" -Value "0" -Type DWord -Force + Start-Sleep 1 +} + +if($SelectiveRegistry.DisableVirtualizationSecurity -and $Global:InstallInfo.Build -ge '22000') { + Log $OptimizeData.SelectiveRegistryDisableVirtualizationSecurity + RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Control\DeviceGuard\Scenarios" -Name "HypervisorEnforcedCodeIntegrity" -Value "0" -Type DWord -Force + RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Control\DeviceGuard" -Name "EnableVirtualizationBasedSecurity" -Value "0" -Type DWord -Force + Start-Sleep 1 +} + + + +if ($SelectiveRegistry.ExplorerUIRibbon) { + if ($Global:InstallInfo.Build -le "19044"){ + Log $OptimizeData.SelectiveRegistryExplorerUIRibbon + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked" -Name "{e2bf9676-5f8f-435c-97eb-11607a5bedf7}" -Value "" -Type String -Force + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked" -Name "{e2bf9676-5f8f-435c-97eb-11607a5bedf7}" -Value "" -Type String -Force + Start-Sleep 1 + } elseif ($Global:InstallInfo.Build -eq "22000") { + Log $OptimizeData.SelectiveRegistryExplorerUIRibbon + # RegKey -Path "HKLM:\WIM_HKCU\Software\Classes\CLSID\{d93ed569-3b3e-4bff-8355-3c44f6a52bb5}\InprocServer32" -Name "(default)" -Value "" -Type String -Force + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Classes\CLSID\{d93ed569-3b3e-4bff-8355-3c44f6a52bb5}\InprocServer32" -Name "(default)" -Value "" -Type String -Force + Start-Sleep 1 + } +} + +RegHives -Unload + +if($SelectiveRegistry.AmoledBlackTheme -and $Global:InstallInfo.Build -ge '10240') { + Log $OptimizeData.SelectiveRegistryAmoledBlackTheme + Import-Registry -Path (Get-ChildItem -Path $OptimizeOffline.SelectiveRegistry -Filter AMOLED_black_theme.reg).FullName + Start-Sleep 1 +} + +if($SelectiveRegistry.RunAsTiContextMenu){ + Log $OptimizeData.SelectiveRegistryRunAsTiContextMenu + Import-Registry -Path (Get-ChildItem -Path $OptimizeOffline.SelectiveRegistry -Filter RunAsTi.reg).FullName + Start-Sleep 1 +} + +Clear-Host diff --git a/Content/Additional/SelectiveRegistry/WindowsPhotoViewer.reg b/Content/Additional/SelectiveRegistry/WindowsPhotoViewer.reg new file mode 100644 index 0000000..2fdecc8 --- /dev/null +++ b/Content/Additional/SelectiveRegistry/WindowsPhotoViewer.reg @@ -0,0 +1,197 @@ +Windows Registry Editor Version 5.00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Photo Viewer\Capabilities\FileAssociations] +".bmp"="PhotoViewer.FileAssoc.BITMAP" +".dib"="PhotoViewer.FileAssoc.BITMAP" +".jpg"="PhotoViewer.FileAssoc.JPEG" +".jpe"="PhotoViewer.FileAssoc.JPEG" +".jpeg"="PhotoViewer.FileAssoc.JPEG" +".jxr"="PhotoViewer.FileAssoc.JPEG" +".jfif"="PhotoViewer.FileAssoc.JFIF" +".wdp"="PhotoViewer.FileAssoc.WDP" +".png"="PhotoViewer.FileAssoc.PNG" +".gif"="PhotoViewer.FileAssoc.TIFF" +".tiff"="PhotoViewer.FileAssoc.TIFF" +".tif"="PhotoViewer.FileAssoc.TIFF" + +; Bitmap + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.BITMAP] +"ImageOptionFlags"=dword:00000001 +"FriendlyTypeName"=hex(2):40,00,25,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,\ + 00,46,00,69,00,6c,00,65,00,73,00,25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,\ + 77,00,73,00,20,00,50,00,68,00,6f,00,74,00,6f,00,20,00,56,00,69,00,65,00,77,\ + 00,65,00,72,00,5c,00,50,00,68,00,6f,00,74,00,6f,00,56,00,69,00,65,00,77,00,\ + 65,00,72,00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,33,00,30,00,35,00,36,00,00,\ + 00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.BITMAP\DefaultIcon] +@="%SystemRoot%\\System32\\imageres.dll,-70" + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.BITMAP\shell] + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.BITMAP\shell\open] + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.BITMAP\shell\open\command] +@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\ + 00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,72,00,75,00,\ + 6e,00,64,00,6c,00,6c,00,33,00,32,00,2e,00,65,00,78,00,65,00,20,00,22,00,25,\ + 00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,46,00,69,00,6c,00,65,00,73,00,\ + 25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,20,00,50,00,68,00,6f,\ + 00,74,00,6f,00,20,00,56,00,69,00,65,00,77,00,65,00,72,00,5c,00,50,00,68,00,\ + 6f,00,74,00,6f,00,56,00,69,00,65,00,77,00,65,00,72,00,2e,00,64,00,6c,00,6c,\ + 00,22,00,2c,00,20,00,49,00,6d,00,61,00,67,00,65,00,56,00,69,00,65,00,77,00,\ + 5f,00,46,00,75,00,6c,00,6c,00,73,00,63,00,72,00,65,00,65,00,6e,00,20,00,25,\ + 00,31,00,00,00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.BITMAP\shell\open\DropTarget] +"CLSID"="{FFE2A43C-56B9-4bf5-9A79-CC6D4285608A}" + + +; JFIF + + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JFIF] +"EditFlags"=dword:00010000 +"ImageOptionFlags"=dword:00000001 +"FriendlyTypeName"=hex(2):40,00,25,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,\ + 00,46,00,69,00,6c,00,65,00,73,00,25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,\ + 77,00,73,00,20,00,50,00,68,00,6f,00,74,00,6f,00,20,00,56,00,69,00,65,00,77,\ + 00,65,00,72,00,5c,00,50,00,68,00,6f,00,74,00,6f,00,56,00,69,00,65,00,77,00,\ + 65,00,72,00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,33,00,30,00,35,00,35,00,00,\ + 00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JFIF\DefaultIcon] +@="%SystemRoot%\\System32\\imageres.dll,-72" + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JFIF\shell] + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JFIF\shell\open] +"MuiVerb"=hex(2):40,00,25,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,46,00,\ + 69,00,6c,00,65,00,73,00,25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,\ + 00,20,00,50,00,68,00,6f,00,74,00,6f,00,20,00,56,00,69,00,65,00,77,00,65,00,\ + 72,00,5c,00,70,00,68,00,6f,00,74,00,6f,00,76,00,69,00,65,00,77,00,65,00,72,\ + 00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,33,00,30,00,34,00,33,00,00,00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JFIF\shell\open\command] +@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\ + 00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,72,00,75,00,\ + 6e,00,64,00,6c,00,6c,00,33,00,32,00,2e,00,65,00,78,00,65,00,20,00,22,00,25,\ + 00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,46,00,69,00,6c,00,65,00,73,00,\ + 25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,20,00,50,00,68,00,6f,\ + 00,74,00,6f,00,20,00,56,00,69,00,65,00,77,00,65,00,72,00,5c,00,50,00,68,00,\ + 6f,00,74,00,6f,00,56,00,69,00,65,00,77,00,65,00,72,00,2e,00,64,00,6c,00,6c,\ + 00,22,00,2c,00,20,00,49,00,6d,00,61,00,67,00,65,00,56,00,69,00,65,00,77,00,\ + 5f,00,46,00,75,00,6c,00,6c,00,73,00,63,00,72,00,65,00,65,00,6e,00,20,00,25,\ + 00,31,00,00,00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JFIF\shell\open\DropTarget] +"CLSID"="{FFE2A43C-56B9-4bf5-9A79-CC6D4285608A}" + + +; Jpeg + + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JPEG] +"EditFlags"=dword:00010000 +"ImageOptionFlags"=dword:00000001 +"FriendlyTypeName"=hex(2):40,00,25,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,\ + 00,46,00,69,00,6c,00,65,00,73,00,25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,\ + 77,00,73,00,20,00,50,00,68,00,6f,00,74,00,6f,00,20,00,56,00,69,00,65,00,77,\ + 00,65,00,72,00,5c,00,50,00,68,00,6f,00,74,00,6f,00,56,00,69,00,65,00,77,00,\ + 65,00,72,00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,33,00,30,00,35,00,35,00,00,\ + 00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JPEG\DefaultIcon] +@="%SystemRoot%\\System32\\imageres.dll,-72" + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JPEG\shell] + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JPEG\shell\open] +"MuiVerb"=hex(2):40,00,25,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,46,00,\ + 69,00,6c,00,65,00,73,00,25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,\ + 00,20,00,50,00,68,00,6f,00,74,00,6f,00,20,00,56,00,69,00,65,00,77,00,65,00,\ + 72,00,5c,00,70,00,68,00,6f,00,74,00,6f,00,76,00,69,00,65,00,77,00,65,00,72,\ + 00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,33,00,30,00,34,00,33,00,00,00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JPEG\shell\open\command] +@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\ + 00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,72,00,75,00,\ + 6e,00,64,00,6c,00,6c,00,33,00,32,00,2e,00,65,00,78,00,65,00,20,00,22,00,25,\ + 00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,46,00,69,00,6c,00,65,00,73,00,\ + 25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,20,00,50,00,68,00,6f,\ + 00,74,00,6f,00,20,00,56,00,69,00,65,00,77,00,65,00,72,00,5c,00,50,00,68,00,\ + 6f,00,74,00,6f,00,56,00,69,00,65,00,77,00,65,00,72,00,2e,00,64,00,6c,00,6c,\ + 00,22,00,2c,00,20,00,49,00,6d,00,61,00,67,00,65,00,56,00,69,00,65,00,77,00,\ + 5f,00,46,00,75,00,6c,00,6c,00,73,00,63,00,72,00,65,00,65,00,6e,00,20,00,25,\ + 00,31,00,00,00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.JPEG\shell\open\DropTarget] +"CLSID"="{FFE2A43C-56B9-4bf5-9A79-CC6D4285608A}" + +; PNG + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.PNG] +"ImageOptionFlags"=dword:00000001 +"FriendlyTypeName"=hex(2):40,00,25,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,\ + 00,46,00,69,00,6c,00,65,00,73,00,25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,\ + 77,00,73,00,20,00,50,00,68,00,6f,00,74,00,6f,00,20,00,56,00,69,00,65,00,77,\ + 00,65,00,72,00,5c,00,50,00,68,00,6f,00,74,00,6f,00,56,00,69,00,65,00,77,00,\ + 65,00,72,00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,33,00,30,00,35,00,37,00,00,\ + 00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.PNG\DefaultIcon] +@="%SystemRoot%\\System32\\imageres.dll,-71" + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.PNG\shell] + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.PNG\shell\open] + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.PNG\shell\open\command] +@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\ + 00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,72,00,75,00,\ + 6e,00,64,00,6c,00,6c,00,33,00,32,00,2e,00,65,00,78,00,65,00,20,00,22,00,25,\ + 00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,46,00,69,00,6c,00,65,00,73,00,\ + 25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,20,00,50,00,68,00,6f,\ + 00,74,00,6f,00,20,00,56,00,69,00,65,00,77,00,65,00,72,00,5c,00,50,00,68,00,\ + 6f,00,74,00,6f,00,56,00,69,00,65,00,77,00,65,00,72,00,2e,00,64,00,6c,00,6c,\ + 00,22,00,2c,00,20,00,49,00,6d,00,61,00,67,00,65,00,56,00,69,00,65,00,77,00,\ + 5f,00,46,00,75,00,6c,00,6c,00,73,00,63,00,72,00,65,00,65,00,6e,00,20,00,25,\ + 00,31,00,00,00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.PNG\shell\open\DropTarget] +"CLSID"="{FFE2A43C-56B9-4bf5-9A79-CC6D4285608A}" + +; WDP + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.WDP] +"EditFlags"=dword:00010000 +"ImageOptionFlags"=dword:00000001 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.WDP\DefaultIcon] +@="%SystemRoot%\\System32\\wmphoto.dll,-400" + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.WDP\shell] + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.WDP\shell\open] +"MuiVerb"=hex(2):40,00,25,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,46,00,\ + 69,00,6c,00,65,00,73,00,25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,\ + 00,20,00,50,00,68,00,6f,00,74,00,6f,00,20,00,56,00,69,00,65,00,77,00,65,00,\ + 72,00,5c,00,70,00,68,00,6f,00,74,00,6f,00,76,00,69,00,65,00,77,00,65,00,72,\ + 00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,33,00,30,00,34,00,33,00,00,00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.WDP\shell\open\command] +@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\ + 00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,72,00,75,00,\ + 6e,00,64,00,6c,00,6c,00,33,00,32,00,2e,00,65,00,78,00,65,00,20,00,22,00,25,\ + 00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,46,00,69,00,6c,00,65,00,73,00,\ + 25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,20,00,50,00,68,00,6f,\ + 00,74,00,6f,00,20,00,56,00,69,00,65,00,77,00,65,00,72,00,5c,00,50,00,68,00,\ + 6f,00,74,00,6f,00,56,00,69,00,65,00,77,00,65,00,72,00,2e,00,64,00,6c,00,6c,\ + 00,22,00,2c,00,20,00,49,00,6d,00,61,00,67,00,65,00,56,00,69,00,65,00,77,00,\ + 5f,00,46,00,75,00,6c,00,6c,00,73,00,63,00,72,00,65,00,65,00,6e,00,20,00,25,\ + 00,31,00,00,00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PhotoViewer.FileAssoc.WDP\shell\open\DropTarget] +"CLSID"="{FFE2A43C-56B9-4bf5-9A79-CC6D4285608A}" + diff --git a/Content/Additional/Setup/Remove-DefaultUser0.cmd b/Content/Additional/Setup/Remove-DefaultUser0.cmd new file mode 100644 index 0000000..198f461 --- /dev/null +++ b/Content/Additional/Setup/Remove-DefaultUser0.cmd @@ -0,0 +1,18 @@ +@ECHO OFF +CD /D "%~dp0" + +NET SESSION >NUL 2>&1 +IF %ERRORLEVEL% NEQ 0 ( + ECHO Permission denied. This script must be run as an Administrator. + ECHO: + PAUSE + EXIT +) ELSE ( + PowerShell.exe -NoProfile -ExecutionPolicy Bypass -File .\Remove-DefaultUser0.ps1 -Argument 2> .\Remove-DefaultUser0.error + DEL /F /Q "%~dp0Remove-DefaultUser0.error" >NUL 2>&1 + DEL /F /Q "%~dp0Remove-DefaultUser0.ps1" >NUL 2>&1 + DEL /F /Q "%~f0" >NUL 2>&1 +) +PAUSE +EXIT + diff --git a/Content/Additional/Setup/Remove-DefaultUser0.ps1 b/Content/Additional/Setup/Remove-DefaultUser0.ps1 new file mode 100644 index 0000000..2ce1c64 --- /dev/null +++ b/Content/Additional/Setup/Remove-DefaultUser0.ps1 @@ -0,0 +1,18 @@ +If (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) +{ + [IO.DirectoryInfo]$ProfilePath = Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" | ForEach-Object -Process { $PSItem.GetValue('ProfileImagePath') } | Where-Object { $PSItem -like "*defaultuser0*" } + If ($ProfilePath.Exists) + { + Clear-Host + Write-Host "Removing the DefaultUser0 profile." -ForegroundColor Yellow + Get-CimInstance -Class Win32_UserProfile | Where-Object { ($PSItem.LocalPath | Split-Path -Leaf) -eq 'defaultuser0' } | Remove-CimInstance + $ProfilePath.Refresh() + If ($ProfilePath.Exists -and (Test-Path -Path $ProfilePath.FullName)) + { + Invoke-Expression -Command ('TAKEOWN /F "{0}"' -f $ProfilePath.FullName) > $null + Invoke-Expression -Command ('ICACLS "{0}" /GRANT *S-1-1-0:F' -f $ProfilePath.FullName) > $null + Invoke-Expression -Command ('CMD RMDIR /S /Q "{0}"' -f $ProfilePath.FullName) > $null + } + } + Else { Exit } +} \ No newline at end of file diff --git a/Content/Additional/Setup/Remove-OneDrive.cmd b/Content/Additional/Setup/Remove-OneDrive.cmd index 7e6b59a..302c0e9 100644 --- a/Content/Additional/Setup/Remove-OneDrive.cmd +++ b/Content/Additional/Setup/Remove-OneDrive.cmd @@ -1,18 +1,2 @@ -@ECHO OFF -CD /D "%~dp0" - -NET SESSION >NUL 2>&1 -IF %ERRORLEVEL% NEQ 0 ( - ECHO Permission denied. This script must be run as an Administrator. - ECHO: - PAUSE - EXIT -) ELSE ( - PowerShell.exe -NoProfile -ExecutionPolicy Bypass -File .\Remove-OneDrive.ps1 -Argument 2> .\Remove-OneDrive.error - DEL /F /Q "%~dp0Remove-OneDrive.error" >NUL 2>&1 - DEL /F /Q "%~dp0Remove-OneDrive.ps1" >NUL 2>&1 - DEL /F /Q "%~f0" >NUL 2>&1 -) -PAUSE -EXIT +PowerShell -NoProfile -ExecutionPolicy Bypass -File ".\Remove-OneDrive.ps1" diff --git a/Content/Additional/Setup/Remove-OneDrive.ps1 b/Content/Additional/Setup/Remove-OneDrive.ps1 index e8db43a..946084f 100644 --- a/Content/Additional/Setup/Remove-OneDrive.ps1 +++ b/Content/Additional/Setup/Remove-OneDrive.ps1 @@ -154,6 +154,19 @@ Function Remove-OneDrive } } +# Ensure we are running with administrative permissions. +If (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + $arguments = @(" Set-ExecutionPolicy Bypass -Scope Process -Force; & '" + $MyInvocation.MyCommand.Definition + "'") + foreach ($param in $PSBoundParameters.GetEnumerator()) { + $arguments += "-"+[string]$param.Key+$(If ($param.Value -notin @("True", "False")) {"="+$param.Value} Else {""}) + } + If(!$noPause){ + $arguments += " ; pause" + } + Start-Process powershell -Verb RunAs -ArgumentList $arguments + Stop-Process -Id $PID +} + If (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Clear-Host diff --git a/Content/Additional/Setup/Run_TI_SetupComplete_online.cmd b/Content/Additional/Setup/Run_TI_SetupComplete_online.cmd new file mode 100644 index 0000000..ff46d09 --- /dev/null +++ b/Content/Additional/Setup/Run_TI_SetupComplete_online.cmd @@ -0,0 +1,41 @@ +@ECHO OFF +TITLE Run SetupComplete.cmd online as TrustedInstaller + +:: RunAsTI (part 1 of 2) - lean and mean snippet by AveYo Source: https://github.com/AveYo/LeanAndMean +whoami|findstr /i /c:"nt authority\system" >nul || ( call :RunAsTI "%~f0" %* & exit/b ) + +pushd "%~dp0" + +CALL "%~dp0SetupComplete.cmd" + +EXIT + +:: RunAsTI (part 2 of 2) - lean and mean snippet by AveYo Source: https://github.com/AveYo/LeanAndMean +#:RunAsTI: #1 snippet to run as TI/System, with /high priority, /priv ownership, explorer and HKCU load +set ^ #=& set "0=%~f0"& set 1=%*& powershell -nop -c iex(([io.file]::ReadAllText($env:0)-split':RunAsTI\:.*')[1])& exit/b +$_CAN_PASTE_DIRECTLY_IN_POWERSHELL='^,^'; function RunAsTI ($cmd) { $id='RunAsTI'; $sid=((whoami /user)-split' ')[-1]; $code=@' +$ti=(whoami /groups)-like"*1-16-16384*"; $DM=[AppDomain]::CurrentDomain."DefineDynamicAss`embly"(1,1)."DefineDynamicMod`ule"(1) +$D=@(); 0..5|% {$D+=$DM."DefineT`ype"("M$_",1179913,[ValueType])}; $I=[int32];$P=$I.module.gettype("System.Int`Ptr"); $U=[uintptr] +$D+=$U; 4..6|% {$D+=$D[$_]."MakeB`yRefType"()};$M=$I.module.gettype("System.Runtime.Interop`Services.Mar`shal");$Z=[uintptr]::size +$S=[string]; $F="kernel","advapi","advapi",($S,$S,$I,$I,$I,$I,$I,$S,$D[7],$D[8]),($U,$S,$I,$I,$D[9]),($U,$S,$I,$I,[byte[]],$I) +0..2|% {$9=$D[0]."DefinePInvokeMeth`od"(("CreateProcess","RegOpenKeyEx","RegSetValueEx")[$_],$F[$_]+'32',8214,1,$S,$F[$_+3],1,4)} +$DF=0,($P,$I,$P),($I,$I,$I,$I,$P,$D[1]),($I,$S,$S,$S,$I,$I,$I,$I,$I,$I,$I,$I,[int16],[int16],$P,$P,$P,$P),($D[3],$P),($P,$P,$I,$I) +1..5|% {$k=$_;$n=1;$AveYo=1; $DF[$_]|% {$9=$D[$k]."DefineFie`ld"('f'+$n++,$_,6)}}; $T=@(); 0..5|% {$T+=$D[$_]."CreateT`ype"()} +0..5|% {nv "A$_" ([Activator]::CreateInstance($T[$_])) -force}; function F ($1,$2) {$T[0]."GetMeth`od"($1).invoke(0,$2)}; +if (!$ti) { $g=0; "TrustedInstaller","lsass"|% {if (!$g) {net1 start $_ 2>&1 >$null; $g=@(get-process -name $_ -ea 0|% {$_})[0]}} + function M($1,$2,$3){$M."GetMeth`od"($1,[type[]]$2).invoke(0,$3)}; $H=@(); $Z,(4*$Z+16)|% {$H+=M "AllocHG`lobal" $I $_}; + M "WriteInt`Ptr" ($P,$P) ($H[0],$g.Handle); $A1.f1=131072;$A1.f2=$Z;$A1.f3=$H[0];$A2.f1=1;$A2.f2=1;$A2.f3=1;$A2.f4=1;$A2.f6=$A1 + $A3.f1=10*$Z+32;$A4.f1=$A3;$A4.f2=$H[1]; M "StructureTo`Ptr" ($D[2],$P,[boolean]) (($A2 -as $D[2]),$A4.f2,$false); $w=0x0E080600 + $out=@($null,"powershell -win 1 -nop -c iex `$env:A",0,0,0,$w,0,$null,($A4 -as $T[4]),($A5 -as $T[5])); F "CreateProcess" $out +} else { $env:A=''; $PRIV=[uri].module.gettype("System.Diagnostics.Process")."GetMeth`ods"(42) |? {$_.Name -eq "SetPrivilege"} + "SeSecurityPrivilege","SeTakeOwnershipPrivilege","SeBackupPrivilege","SeRestorePrivilege" |% {$PRIV.Invoke(0, @("$_",2))} + $HKU=[uintptr][uint32]2147483651; $LNK=$HKU; $reg=@($HKU,"S-1-5-18",8,2,($LNK -as $D[9])); F "RegOpenKeyEx" $reg; $LNK=$reg[4] + function SYM($1,$2){$b=[Text.Encoding]::Unicode.GetBytes("\Registry\User\$1");@($2,"SymbolicLinkValue",0,6,[byte[]]$b,$b.Length)} + F "RegSetValueEx" (SYM $(($key-split'\\')[1]) $LNK); $EXP="HKLM:\Software\Classes\AppID\{CDCBCFCA-3CDC-436f-A4E2-0E02075250C2}" + $r="explorer"; if (!$cmd) {$cmd='C:\'}; $dir=test-path -lit ((($cmd -split '^("[^"]+")|^([^\s]+)') -ne'')[0].trim('"')) -type 1 + if (!$dir) {$r="start `"$id`" /high /w"}; sp $EXP RunAs '' -force; start cmd -args ("/q/x/d/r title $id && $r",$cmd) -wait -win 1 + do {sleep 7} while ((gwmi win32_process -filter 'name="explorer.exe"'|? {$_.getownersid().sid -eq "S-1-5-18"})) + F "RegSetValueEx" (SYM ".Default" $LNK); sp $EXP RunAs "Interactive User" -force } # lean and mean snippet by AveYo, 2018-2021 +'@; $key="Registry::HKEY_USERS\$sid\Volatile Environment"; $a1="`$id='$id';`$key='$key';";$a2="`$cmd='$($cmd-replace"'","''")';`n" +sp $key $id $($a1,$a2,$code) -type 7 -force; $arg="$a1 `$env:A=(gi `$key).getvalue(`$id)-join'';rp `$key `$id -force; iex `$env:A" +$_PRESS_ENTER='^,^'; start powershell -args "-win 1 -nop -c $arg" -verb runas }; <#,#> RunAsTI $env:1; #:RunAsTI: diff --git a/Content/Additional/Setup/Services.json b/Content/Additional/Setup/Services.json index 248634d..b9b9854 100644 Binary files a/Content/Additional/Setup/Services.json and b/Content/Additional/Setup/Services.json differ diff --git a/Content/Additional/Setup/Set-Additional.cmd b/Content/Additional/Setup/Set-Additional.cmd index 99c7670..a8d9db9 100644 --- a/Content/Additional/Setup/Set-Additional.cmd +++ b/Content/Additional/Setup/Set-Additional.cmd @@ -1,18 +1 @@ -@ECHO OFF -CD /D "%~dp0" - -NET SESSION >NUL 2>&1 -IF %ERRORLEVEL% NEQ 0 ( - ECHO Permission denied. This script must be run as an Administrator. - ECHO: - PAUSE - EXIT -) ELSE ( - PowerShell.exe -NoProfile -ExecutionPolicy Bypass -File .\Set-Additional.ps1 -Argument 2> .\Set-Additional.error - DEL /F /Q "%~dp0Set-Additional.error" >NUL 2>&1 - DEL /F /Q "%~dp0Set-Additional.ps1" >NUL 2>&1 - DEL /F /Q "%~f0" >NUL 2>&1 -) -PAUSE -EXIT - +PowerShell -NoProfile -ExecutionPolicy Bypass -File ".\Set-Additional.ps1" \ No newline at end of file diff --git a/Content/Additional/Setup/Set-Additional.ps1 b/Content/Additional/Setup/Set-Additional.ps1 index 55576c7..44b60cf 100644 --- a/Content/Additional/Setup/Set-Additional.ps1 +++ b/Content/Additional/Setup/Set-Additional.ps1 @@ -17,7 +17,7 @@ Function Set-Additional If ((Get-ExecutionPolicy -Scope CurrentUser) -ne 'RemoteSigned') { Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm:$false } If ((Get-ExecutionPolicy -Scope LocalMachine) -ne 'RemoteSigned') { Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Confirm:$false } - # Get the current build number for the Windows 10 version. + # Get the current build number for the Windows version. $Build = Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber If (Test-Path -Path .\ScheduledTasks.json) @@ -118,7 +118,7 @@ Function Set-Additional } # Disable Clipboard history, its synchronization service and any Remote Desktop redirection. - If ($Build -ge 17763) + If ($Build -lt 19041) { If (!(Test-Path -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -ItemType Directory -Force | Out-Null } Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name AllowCrossDeviceClipboard -Value 0 -Force @@ -127,7 +127,10 @@ Function Set-Additional Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Terminal Server Client" -Name DisableClipboardRedirection -Value 1 -Force If (!(Test-Path -Path "HKCU:\Software\Microsoft\Clipboard")) { New-Item -Path "HKCU:\Software\Microsoft\Clipboard" -ItemType Directory -Force | Out-Null } Set-ItemProperty -Path "HKCU:\Software\Microsoft\Clipboard" -Name EnableClipboardHistory -Value 0 -Force - Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\cbdhsvc" -Name Start -Value 4 -Force + } + + If ($Build -ge 18363) { + Set-ItemProperty -Path "HKCU:\SOFTWARE\Classes\CLSID\{1d64637d-31e9-4b06-9124-e83fb178ac6e}\TreatAs" -Name "(Default)" -Value "{64bc32b5-4eec-4de7-972d-bd8bd0324537}" -Force } # Uninstall Cortana. @@ -140,15 +143,14 @@ Function Set-Additional If ((Get-ItemPropertyValue -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" -Name DrvType) -eq 'SSD') { - # Enable TRIM support for NTFS and ReFS file systems for SSD drives. + # Enable TRIM support for NTFS and ReFS file systems. Invoke-Expression -Command ('FSUTIL BEHAVIOR SET DISABLEDELETENOTIFY NTFS 0') | Out-Null - $QueryReFS = Invoke-Expression -Command ('FSUTIL BEHAVIOR QUERY DISABLEDELETENOTIFY') | Select-String -Pattern ReFS - If ($QueryReFS) { Invoke-Expression -Command ('FSUTIL BEHAVIOR SET DISABLEDELETENOTIFY REFS 0') | Out-Null } + If (Invoke-Expression -Command ('FSUTIL BEHAVIOR QUERY DISABLEDELETENOTIFY') | Select-String -Pattern ReFS) { Invoke-Expression -Command ('FSUTIL BEHAVIOR SET DISABLEDELETENOTIFY REFS 0') | Out-Null } - # Disable Swapfile.sys which can improve SSD performance. + # Disable Swapfile.sys which can improve SSD performance Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management" -Name SwapfileControl -Value 0 -Force - # Disable Prefetch and Superfetch (optimal for SSD drives). + # Disable Prefetch and Superfetch (optimal for SSD drives) If (!(Test-Path -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters")) { New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" -ItemType Directory -Force | Out-Null } Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" -Name EnablePrefetcher -Value 0 -Force Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" -Name EnableSuperfetch -Value 0 -Force @@ -161,6 +163,10 @@ Function Set-Additional } Else { + # If the Ultimate Performance power scheme is not available, duplicate the power scheme's GUID so it becomes available. Finally, set the active power scheme to Ultimate Performance + If (!(Get-CimInstance -ClassName Win32_PowerPlan -Namespace root\cimv2\power -Filter "ElementName = 'Ultimate Performance'")) { Invoke-Expression -Command ('POWERCFG -DUPLICATESCHEME e9a42b02-d5df-448d-aa00-03f14749eb61') } + Invoke-Expression -Command ('POWERCFG -S e9a42b02-d5df-448d-aa00-03f14749eb61') | Out-Null + # Disable hibernation. Invoke-Expression -Command ('POWERCFG -H OFF') | Out-Null @@ -169,11 +175,6 @@ Function Set-Additional $PSItem.AllowComputerToTurnOffDevice = 'Disabled' $PSItem | Set-NetAdapterPowerManagement } - - # Set the active power scheme to Ultimate Performance if the runtime Windows version is Windows 10 Pro for Workstations or the Ultimate Performance power scheme GUID is detected, else set the active power scheme to High Performance. - If ((Get-WindowsEdition -Online | Select-Object -ExpandProperty Edition) -eq 'ProfessionalWorkstation') { Invoke-Expression -Command ('POWERCFG -S e9a42b02-d5df-448d-aa00-03f14749eb61') | Out-Null } - ElseIf (POWERCFG -L | Out-String | Select-String -Pattern 'e9a42b02-d5df-448d-aa00-03f14749eb61') { Invoke-Expression -Command ('POWERCFG -S e9a42b02-d5df-448d-aa00-03f14749eb61') | Out-Null } - Else { Invoke-Expression -Command ('POWERCFG -S 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c') | Out-Null } } # Use the total amount of memory installed on the device to modify the svchost.exe split threshold to reduce the amount of svchost.exe processes that run simultaneously. @@ -197,10 +198,11 @@ Function Set-Additional If ($RequestReboot -eq [Windows.MessageBoxResult]::Yes) { Clear-Host + Remove-Item -Path $PSScriptRoot\Set-Additional.error -Force -ErrorAction Ignore $ProgressPreference = 'Continue' - ForEach ($Count In (1 .. 15)) + ForEach ($Count In (1 .. 5)) { - Write-Progress -Id 1 -Activity "Restarting $Env:COMPUTERNAME" -Status "Restarting in 15 seconds, $(15 - $Count) seconds left" -PercentComplete (($Count / 15) * 100) + Write-Progress -Id 1 -Activity "Restarting $Env:COMPUTERNAME" -Status "Restarting in 5 seconds, $(5 - $Count) seconds left" -PercentComplete (($Count / 5) * 100) Start-Sleep 1 } Restart-Computer -Force @@ -214,6 +216,19 @@ Function Set-Additional } } +# Ensure we are running with administrative permissions. +If (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + $arguments = @(" Set-ExecutionPolicy Bypass -Scope Process -Force; & '" + $MyInvocation.MyCommand.Definition + "'") + foreach ($param in $PSBoundParameters.GetEnumerator()) { + $arguments += "-"+[string]$param.Key+$(If ($param.Value -notin @("True", "False")) {"="+$param.Value} Else {""}) + } + If(!$noPause){ + $arguments += " ; pause" + } + Start-Process powershell -Verb RunAs -ArgumentList $arguments + Stop-Process -Id $PID +} + If (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Clear-Host diff --git a/Content/Additional/Setup/SetupComplete.cmd b/Content/Additional/Setup/SetupComplete.cmd index 6617bdb..ea57998 100644 --- a/Content/Additional/Setup/SetupComplete.cmd +++ b/Content/Additional/Setup/SetupComplete.cmd @@ -4,6 +4,7 @@ REM Answer files should ALWAYS be removed from the 'Windows\Panther' and 'Window PowerShell.exe -NoProfile -ExecutionPolicy Bypass -File "%WINDIR%\Setup\Scripts\Refresh-Explorer.ps1" DEL /F /Q "%WINDIR%\Setup\Scripts\Refresh-Explorer.ps1" >NUL 2>&1 +DEL /F /Q "%WINDIR%\Setup\Scripts\Run_TI_SetupComplete_online.cmd >NUL 2>&1 DEL /F /Q "%WINDIR%\Panther\unattend.xml" >NUL 2>&1 DEL /F /Q "%WINDIR%\System32\Sysprep\unattend.xml" >NUL 2>&1 -DEL "%~f0" \ No newline at end of file +DEL "%~f0" diff --git a/Content/Additional/Unattend/unattend.xml b/Content/Additional/Unattend/unattend.xml new file mode 100644 index 0000000..33c78c1 --- /dev/null +++ b/Content/Additional/Unattend/unattend.xml @@ -0,0 +1,16 @@ + + + + + + true + true + true + true + 3 + false + + false + + + \ No newline at end of file diff --git a/Content/Additional/Unattend/unattend_basic.xml b/Content/Additional/Unattend/unattend_basic.xml new file mode 100644 index 0000000..33c78c1 --- /dev/null +++ b/Content/Additional/Unattend/unattend_basic.xml @@ -0,0 +1,16 @@ + + + + + + true + true + true + true + 3 + false + + false + + + \ No newline at end of file diff --git a/Content/AppxWhitelist.json b/Content/AppxWhitelist.json deleted file mode 100644 index f9436bb..0000000 Binary files a/Content/AppxWhitelist.json and /dev/null differ diff --git a/Content/Assets/PlaceAssets.txt b/Content/Assets/PlaceAssets.txt new file mode 100644 index 0000000..6c0b9e0 --- /dev/null +++ b/Content/Assets/PlaceAssets.txt @@ -0,0 +1,3 @@ +Place different assets here +You can place windows.ico - used as the windows local disk icon +setup.ico - used as the USB/ISO icon \ No newline at end of file diff --git a/Content/Assets/setup.ico b/Content/Assets/setup.ico new file mode 100644 index 0000000..fbd1184 Binary files /dev/null and b/Content/Assets/setup.ico differ diff --git a/Content/CustomAppAssociations.xml b/Content/CustomAppAssociations.xml index ad2b6a7..399c50a 100644 --- a/Content/CustomAppAssociations.xml +++ b/Content/CustomAppAssociations.xml @@ -3,22 +3,13 @@ - + - + - - - - - - - - - - - + + @@ -31,24 +22,30 @@ - - - - - - - - - + + + + + + + + + + + + + + + + - \ No newline at end of file diff --git a/Content/Lists/Capabilities/CapabilitiesList.json b/Content/Lists/Capabilities/CapabilitiesList.json new file mode 100644 index 0000000..3c4f7ee --- /dev/null +++ b/Content/Lists/Capabilities/CapabilitiesList.json @@ -0,0 +1,5 @@ +{ + "Name": [ + + ] + } \ No newline at end of file diff --git a/Content/Lists/Capabilities/CapabilitiesTemplate.json b/Content/Lists/Capabilities/CapabilitiesTemplate.json new file mode 100644 index 0000000..4471978 --- /dev/null +++ b/Content/Lists/Capabilities/CapabilitiesTemplate.json @@ -0,0 +1,5 @@ +{ + "Name": [ + + ] +} diff --git a/Content/Lists/FeaturesToDisable/FeaturesToDisableList.json b/Content/Lists/FeaturesToDisable/FeaturesToDisableList.json new file mode 100644 index 0000000..f498830 --- /dev/null +++ b/Content/Lists/FeaturesToDisable/FeaturesToDisableList.json @@ -0,0 +1,5 @@ +{ + "FeatureName" : [ + + ] +} diff --git a/Content/Lists/FeaturesToDisable/FeaturesToDisableTemplate.json b/Content/Lists/FeaturesToDisable/FeaturesToDisableTemplate.json new file mode 100644 index 0000000..298df67 --- /dev/null +++ b/Content/Lists/FeaturesToDisable/FeaturesToDisableTemplate.json @@ -0,0 +1,5 @@ +{ + "FeatureName": [ + + ] +} diff --git a/Content/Lists/FeaturesToEnable/FeaturesToEnableList.json b/Content/Lists/FeaturesToEnable/FeaturesToEnableList.json new file mode 100644 index 0000000..f498830 --- /dev/null +++ b/Content/Lists/FeaturesToEnable/FeaturesToEnableList.json @@ -0,0 +1,5 @@ +{ + "FeatureName" : [ + + ] +} diff --git a/Content/Lists/FeaturesToEnable/FeaturesToEnableTemplate.json b/Content/Lists/FeaturesToEnable/FeaturesToEnableTemplate.json new file mode 100644 index 0000000..298df67 --- /dev/null +++ b/Content/Lists/FeaturesToEnable/FeaturesToEnableTemplate.json @@ -0,0 +1,5 @@ +{ + "FeatureName": [ + + ] +} diff --git a/Content/Lists/Packages/PackagesList.json b/Content/Lists/Packages/PackagesList.json new file mode 100644 index 0000000..a3c3ebc --- /dev/null +++ b/Content/Lists/Packages/PackagesList.json @@ -0,0 +1,5 @@ +{ + "PackageName": [ + + ] +} diff --git a/Content/Lists/Packages/PackagesTemplate.json b/Content/Lists/Packages/PackagesTemplate.json new file mode 100644 index 0000000..da05129 --- /dev/null +++ b/Content/Lists/Packages/PackagesTemplate.json @@ -0,0 +1,5 @@ +{ + "PackageName": [ + + ] +} diff --git a/Content/Lists/Services/ServicesAdvanced.json b/Content/Lists/Services/ServicesAdvanced.json new file mode 100644 index 0000000..24866c6 --- /dev/null +++ b/Content/Lists/Services/ServicesAdvanced.json @@ -0,0 +1,13 @@ +{ + "__Info": [ + "start key values", + "0 = Boot", + "1 = System", + "2 = Automatic", + "3 = Manual", + "4 = Disabled" + ], + "Services": [ + + ] +} \ No newline at end of file diff --git a/Content/Lists/Services/ServicesList.json b/Content/Lists/Services/ServicesList.json new file mode 100644 index 0000000..6290035 --- /dev/null +++ b/Content/Lists/Services/ServicesList.json @@ -0,0 +1,8 @@ +{ + "__Info": [ + "Insert the services display names as a list, the names are found in the ./ServicesTemplate.json in the 'name' key" + ], + "Services": [ + + ] +} diff --git a/Content/Lists/Services/ServicesTemplate.json b/Content/Lists/Services/ServicesTemplate.json new file mode 100644 index 0000000..9ac65b5 --- /dev/null +++ b/Content/Lists/Services/ServicesTemplate.json @@ -0,0 +1,13 @@ +{ + "__Info": [ + "start key values", + "0 = Boot", + "1 = System", + "2 = Automatic", + "3 = Manual", + "4 = Disabled" + ], + "Services": [ + + ] +} diff --git a/Content/Lists/SystemApps/SystemAppsList.json b/Content/Lists/SystemApps/SystemAppsList.json new file mode 100644 index 0000000..960e422 --- /dev/null +++ b/Content/Lists/SystemApps/SystemAppsList.json @@ -0,0 +1,5 @@ +{ + "DisplayName": [ + + ] +} \ No newline at end of file diff --git a/Content/Lists/SystemApps/SystemAppsTemplate.json b/Content/Lists/SystemApps/SystemAppsTemplate.json new file mode 100644 index 0000000..d3a4575 --- /dev/null +++ b/Content/Lists/SystemApps/SystemAppsTemplate.json @@ -0,0 +1,5 @@ +{ + "DisplayName": [ + + ] +} diff --git a/Content/Lists/WindowsApps/WindowsAppsList.json b/Content/Lists/WindowsApps/WindowsAppsList.json new file mode 100644 index 0000000..3f3ebae --- /dev/null +++ b/Content/Lists/WindowsApps/WindowsAppsList.json @@ -0,0 +1,5 @@ +{ + "DisplayName": [ + + ] +} diff --git a/Content/Lists/WindowsApps/WindowsAppsTemplate.json b/Content/Lists/WindowsApps/WindowsAppsTemplate.json new file mode 100644 index 0000000..d3a4575 --- /dev/null +++ b/Content/Lists/WindowsApps/WindowsAppsTemplate.json @@ -0,0 +1,5 @@ +{ + "DisplayName": [ + + ] +} diff --git a/Optimize-Offline.psd1 b/Optimize-Offline.psd1 index a7744f6..999742a 100644 --- a/Optimize-Offline.psd1 +++ b/Optimize-Offline.psd1 @@ -1,6 +1,6 @@ <# =========================================================================== - Created with: SAPIEN Technologies, Inc., PowerShell Studio 2019 v5.7.182 + Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.194 Created on: 11/20/2019 11:53 AM Created by: BenTheGreat Filename: Optimize-Offline.psd1 @@ -14,10 +14,11 @@ @{ GUID = '86c4db30-1a45-43c7-a96b-46d2a1d84671' RootModule = 'Optimize-Offline.psm1' - ModuleVersion = '4.0.1.7' + ModuleVersion = '4.0.1.9' + ModuleForkVersion = 'gdeliana-7.1' Author = 'Ben White' - Copyright = '(c) 2020. All rights reserved.' - Description = 'The Optimize-Offline module enables the offline optimizing of Windows 10 image (WIM/ESD) files for optimal runtime environments.' + Copyright = '(c) 2021. All rights reserved.' + Description = 'The Optimize-Offline module enables the offline optimizing of Windows images (WIM/ESD) files for optimal runtime environments.' HelpInfoUri = 'https://github.com/DrEmpiricism/Optimize-Offline/blob/master/en-US/Optimize-Offline-help.xml' PowerShellVersion = '5.1' DotNetFrameworkVersion = '4.0' @@ -30,7 +31,7 @@ CmdletsToExport = @() PrivateData = @{ PSData = @{ - Tags = @('Image Optimization', 'WIM Optimization', 'Offline Windows Image', 'Offline Servicing', 'Offline Imaging', 'WIM', 'SWM', 'ESD', 'Windows 10', 'LTSC', 'Enterprise', '19H1', '19H2', '20H1', '20H2', 'Deployment', 'Debloat', 'DISM', 'PSModule') + Tags = @('Image Optimization', 'WIM Optimization', 'Offline Windows Image', 'Offline Servicing', 'Offline Imaging', 'WIM', 'SWM', 'ESD', 'Windows 10', 'Windows 11', 'LTSC', 'Enterprise', '19H1', '19H2', '20H1', '20H2', '21H1', '21H2', 'Deployment', 'Debloat', 'DISM', 'PSModule') LicenseUri = 'https://github.com/DrEmpiricism/Optimize-Offline/blob/master/LICENSE' ProjectUri = 'https://github.com/DrEmpiricism/Optimize-Offline' ReleaseNotes = 'https://github.com/DrEmpiricism/Optimize-Offline/blob/master/ChangeLog.md' diff --git a/Optimize-Offline.psm1 b/Optimize-Offline.psm1 index fc991f3..772967b 100644 --- a/Optimize-Offline.psm1 +++ b/Optimize-Offline.psm1 @@ -4,12 +4,12 @@ #Requires -Module Dism <# =========================================================================== - Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.191 + Created with: SAPIEN Technologies, Inc., PowerShell Studio 2023 v5.8.218 Created on: 11/20/2019 11:53 AM Created by: BenTheGreat Filename: Optimize-Offline.psm1 - Version: 4.0.1.8 - Last updated: 06/22/2021 + Version: 4.0.1.10 + Last updated: 02/16/2023 ------------------------------------------------------------------------- Module Name: Optimize-Offline =========================================================================== @@ -25,23 +25,26 @@ Function Optimize-Offline ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, - HelpMessage = 'The full path to a Windows 10 Installation Media ISO, or a Windows 10 WIM, SWM or ESD file.')] - [ValidateScript( { - If ($PSItem.Exists -and $PSItem.Extension -eq '.ISO' -or $PSItem.Extension -eq '.WIM' -or $PSItem.Extension -eq '.SWM' -or $PSItem.Extension -eq '.ESD') { $true } - Else { Throw ('Invalid source path: "{0}"' -f $PSItem.FullName) } - })] - [IO.FileInfo]$SourcePath, + HelpMessage = 'The full path to a Windows Installation Media ISO, or a Windows WIM, SWM or ESD file.')] + [Object]$SourcePath, [Parameter(HelpMessage = 'Selectively or automatically deprovisions Windows Apps and removes their associated provisioning packages (.appx or .appxbundle).')] - [ValidateSet('Select', 'Whitelist', 'All')] + [ValidateSet('None', 'Select', 'Whitelist', 'Blacklist', 'All', IgnoreCase = $true)] [String]$WindowsApps, [Parameter(HelpMessage = 'Populates and outputs a Gridview list of System Apps for selective removal.')] - [Switch]$SystemApps, + [ValidateSet('None', 'Select', 'Whitelist', 'Blacklist', 'All', IgnoreCase = $true)] + [String]$SystemApps, [Parameter(HelpMessage = 'Populates and outputs a Gridview list of Capability Packages for selective removal.')] - [Switch]$Capabilities, + [ValidateSet('None', 'Select', 'Whitelist', 'Blacklist', 'All', IgnoreCase = $true)] + [String]$Capabilities, [Parameter(HelpMessage = 'Populates and outputs a Gridview list of Windows Cabinet File Packages for selective removal.')] - [Switch]$Packages, + [ValidateSet('None', 'Select', 'Whitelist', 'Blacklist', 'All', IgnoreCase = $true)] + [String]$Packages, + [ValidateSet('None', 'Select', 'List', 'All', IgnoreCase = $true)] [Parameter(HelpMessage = 'Populates and outputs a Gridview list of Windows Optional Features for selective disabling and enabling.')] - [Switch]$Features, + [String]$FeaturesToEnable, + [ValidateSet('None', 'Select', 'List', 'All', IgnoreCase = $true)] + [Parameter(HelpMessage = 'Populates and outputs a Gridview list of Windows Optional Features for selective disabling and enabling.')] + [String]$FeaturesToDisable, [Parameter(HelpMessage = 'Integrates the Developer Mode Feature into the image.')] [Switch]$DeveloperMode, [Parameter(HelpMessage = 'Integrates the Microsoft Windows Store and its required dependencies into the image.')] @@ -50,20 +53,55 @@ Function Optimize-Offline [Switch]$MicrosoftEdge, [Parameter(HelpMessage = 'Integrates the traditional Win32 Calculator into the image.')] [Switch]$Win32Calc, + [Parameter(HelpMessage = 'Disable Windows defender while retaining the option to reactivate it.')] + [Switch]$DormantDefender, [Parameter(HelpMessage = 'Integrates the Windows Server Data Deduplication Feature into the image.')] [Switch]$Dedup, [Parameter(HelpMessage = 'Integrates the Microsoft Diagnostic and Recovery Toolset (DaRT 10) and Windows 10 Debugging Tools into Windows Setup and Windows Recovery.')] - [ValidateSet('Setup', 'Recovery')] + [ValidateSet('Setup', 'Recovery', IgnoreCase = $true)] [String[]]$DaRT, [Parameter(HelpMessage = 'Applies optimized settings to the image registry hives.')] [Switch]$Registry, + [Parameter(HelpMessage = 'Sets the output path')] + [String]$OutputPath, [Parameter(HelpMessage = 'Integrates user-specific content added to the "Content/Additional" directory into the image when enabled within the hashtable.')] [Hashtable]$Additional = @{ Setup = $false; Wallpaper = $false; SystemLogo = $false; LockScreen = $false; RegistryTemplates = $false; LayoutModification = $false; Unattend = $false; Drivers = $false; NetFx3 = $false }, [Parameter(HelpMessage = 'Performs a clean-up of the Component Store by compressing all superseded components.')] [Switch]$ComponentCleanup, [Parameter(HelpMessage = 'Creates a new bootable Windows Installation Media ISO.')] - [ValidateSet('Prompt', 'No-Prompt')] - [String]$ISO + [ValidateSet('Prompt', 'No-Prompt', IgnoreCase = $true)] + [String]$ISO, + [Parameter(Mandatory=$false)] [Switch]$populateLists, + [Parameter(Mandatory=$false)] [Switch]$populateTemplates, + [Parameter(Mandatory=$false)] + [ValidateSet('Select', 'None', 'Fast', 'Maximum', 'Solid', IgnoreCase = $true)] + [String]$CompressionType, + [Parameter(Mandatory=$false)] + [Hashtable]$SelectiveRegistry = @{ + DisableWindowsUpgrade = $false + DisableWindowsUpdateMicrosoft = $false + DisableDriverUpdate = $false + DormantOneDrive = $false + Disable3rdPartyApps = $false + W11ClassicContextMenu = $false + ExplorerUIRibbon = $false + ClassicSearchExplorer = $false + RemoveTaskbarPinnedIcons = $false + DisableTeamsApp = $false + DisableVirtualizationSecurity = $false + RunAsTiContextMenu = $false + AmoledBlackTheme = $false + }, + [Parameter(HelpMessage = 'Shutdown PC on script completion')] + [Switch]$ShutDownOnComplete = $false, + [Parameter(HelpMessage = 'Removal of windows services.')] + [ValidateSet('None', 'List', 'Advanced', 'Select', IgnoreCase = $true)] + [String]$Services, + [Parameter(HelpMessage = 'Set USB booting support')] + [ValidateSet('Off', 'Legacy', 'UEFI', IgnoreCase = $true)] + [String]$FlashToUSB = "Off", + [Parameter(Mandatory = $false, HelpMessage = 'Set USB Drive to flash the ISO')] + [Int]$FlashUSBDriveNumber = -1 ) Begin @@ -73,6 +111,7 @@ Function Optimize-Offline $ErrorActionPreference = 'SilentlyContinue' $Global:ProgressPreference = 'SilentlyContinue' $Host.UI.RawUI.BackgroundColor = 'Black' + If ($PSVersionTable.PSVersion.Major -eq 7) { $PSStyle.OutputRendering = 'Host' } Clear-Host Test-Requirements If (Get-WindowsImage -Mounted) { Dismount-Images; Clear-Host } @@ -100,12 +139,43 @@ Function Optimize-Offline #endregion Create the Working File Structure #region Media Export + $SourcePath = [IO.FileInfo]$SourcePath + $allowedExtensions = @('.iso', '.wim', '.swm', '.esd') + If (-not $SourcePath.Exists -or [String]$SourcePath.Extension.ToLower() -notin $allowedExtensions) { + Add-Type -AssemblyName System.Windows.Forms + + $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ + InitialDirectory = [Environment]::GetFolderPath('Desktop') + Filter = 'All allowed types|*.wim;*.swm;*.iso;*.esd;*.WIM;*.SWM;*.ISO;*.ESD' + Multiselect = $false + AddExtension = $true + CheckPathExists = $true + } + + $null = $FileBrowser.ShowDialog() + + if($FileBrowser.FileName){ + $SourcePath = Get-Item -Path $FileBrowser.FileName + } + } + + if(-not $SourcePath.Exists) { Throw ('Invalid source path: "{0}"' -f [String]$SourcePath) } + Switch ($SourcePath.Extension) { '.ISO' { - $ISOMount = (Mount-DiskImage -ImagePath $SourcePath.FullName -StorageType ISO -PassThru | Get-Volume).DriveLetter + ':' - [Void](Get-PSDrive) + Try{ + $DrivesBefore = [System.Collections.ArrayList]@() + Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Free -eq 0} | ForEach-Object -Process { + [Void]$DrivesBefore.Add($PSItem.Name) + } + [Void](Mount-DiskImage -ImagePath $SourcePath.FullName -StorageType ISO) + $ISOMount = "$((Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Free -eq 0 -and $_.Name -notin $DrivesBefore}).Name):" + } Catch { + $ISOMount = "" + } + If (!(Get-ChildItem -Path (GetPath -Path $ISOMount -Child sources) -Filter install* -File)) { $PSCmdlet.WriteWarning($OptimizeData.InvalidWindowsInstallMedia -f $SourcePath.Name) @@ -124,6 +194,10 @@ Function Optimize-Offline ForEach ($Item In Get-ChildItem -Path $ISOMount -Recurse) { $ISOExport = $ISOMedia.FullName + $Item.FullName.Replace($ISOMount, $null) + $destPathDir = $(Split-Path $ISOExport) + If (!(Test-Path -Path $destPathDir)) { + [Void](New-Item -path $(Split-Path $ISOExport) -ItemType Directory -Force) + } Copy-Item -Path $Item.FullName -Destination $ISOExport } Do @@ -194,13 +268,25 @@ Function Optimize-Offline } #endregion Media Export + #region USB device selection + $null = $USBDrive + If ($FlashToUSB.ToLower().Trim() -ne "off" -and !$populateLists -and !$populateTemplates) { + $USBDrive = Get-Disk | Where-Object BusType -eq USB + If($FlashUSBDriveNumber -ge 0) { + $USBDrive = $USBDrive | Where-Object Number -eq $FlashUSBDriveNumber + } Else { + $USBDrive = $USBDrive | Out-GridView -Title 'Select USB Drive to Format' -OutputMode Single + } + } + #endregion USB device selection + #region Image and Metadata Validation If ((Get-WindowsImage -ImagePath $InstallWim -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1).Count -gt 1) { Do { $Host.UI.RawUI.WindowTitle = $OptimizeData.SelectWindowsEdition - $EditionList = Get-WindowsImage -ImagePath $InstallWim -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Select-Object -Property @{ Label = 'Index'; Expression = { ($PSItem.ImageIndex) } }, @{ Label = 'Name'; Expression = { ($PSItem.ImageName) } }, @{ Label = 'Size (GB)'; Expression = { '{0:N2}' -f ($PSItem.ImageSize / 1GB) } } | Out-GridView -Title "Select the Windows 10 Edition to Optimize." -OutputMode Single + $EditionList = Get-WindowsImage -ImagePath $InstallWim -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Select-Object -Property @{ Label = 'Index'; Expression = { ($PSItem.ImageIndex) } }, @{ Label = 'Name'; Expression = { ($PSItem.ImageName) } }, @{ Label = 'Size (GB)'; Expression = { '{0:N2}' -f ($PSItem.ImageSize / 1GB) } } | Out-GridView -Title $OptimizeData.SelectWindowsEdition -OutputMode Single } While ($EditionList.Length -eq 0) $ImageIndex = $EditionList.Index @@ -211,6 +297,8 @@ Function Optimize-Offline { $Host.UI.RawUI.WindowTitle = "Validating Image Metadata." $InstallInfo = $InstallWim | Get-ImageData -Index $ImageIndex -ErrorAction Stop + $Global:InstallInfo = $InstallInfo + $InstallInfo | ConvertTo-Json | Out-File -FilePath "$($OptimizeOffline.GUI.Main)\image_info.json" -Encoding UTF8 -Force -ErrorAction Ignore } Catch { @@ -219,6 +307,30 @@ Function Optimize-Offline Break } + If($OutputPath.ToLower().Trim() -eq 'select'){ + Add-Type -AssemblyName System.Windows.Forms + If($SourcePath.Extension.ToLower() -eq '.iso'){ + $SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog + $SaveFileDialog.InitialDirectory = [Environment]::GetFolderPath('Desktop') + $SaveFileDialog.FileName = ($($InstallInfo.Edition).Replace(' ', '') + "_$($InstallInfo.Build)") + $SaveFileDialog.Filter = "ISO files (*.iso)| *.iso" + If($SaveFileDialog.ShowDialog() -eq 'Ok'){ + $OutputPath = $SaveFileDialog.FileName + } + } Else { + $FolderBrowserDialog = New-Object System.Windows.Forms.FolderBrowserDialog + $null = $FolderBrowserDialog.ShowDialog() + $OutputPath = $FolderBrowserDialog.SelectedPath + } + } + + If ($InstallInfo.Build -ge 22000 -and -not $BootWim -and $ISOMedia.Exists) + { + Try { $BootWim = Get-ChildItem -Path (GetPath -Path $ISOMedia.FullName -Child sources) -Filter boot.* -File | Move-Item -Destination $ImageFolder -PassThru -ErrorAction Stop | Set-ItemProperty -Name IsReadOnly -Value $false -PassThru | Get-Item | Select-Object -ExpandProperty FullName } + Catch [Management.Automation.ItemNotFoundException] { Break } + $DynamicParams.BootImage = $true + } + If ($InstallInfo.VersionTable.Major -ne 10) { $PSCmdlet.WriteWarning($OptimizeData.UnsupportedImageVersion -f $InstallInfo.Version) @@ -233,19 +345,19 @@ Function Optimize-Offline Break } - If ($InstallInfo.InstallationType.Contains('Server') -or $InstallInfo.InstallationType.Contains('WindowsPE')) + If ($InstallInfo.InstallationType.Contains('WindowsPE')) { $PSCmdlet.WriteWarning($OptimizeData.UnsupportedImageType -f $InstallInfo.InstallationType) $TempDirectory | Purge Break } - If ($InstallInfo.Build -ge '17134' -and $InstallInfo.Build -le '19041') + If ($InstallInfo.Build -ge '17134') { If ($InstallInfo.Name -like "*LTSC*") { $DynamicParams.LTSC = $true - If ($WindowsApps) { Remove-Variable -Name WindowsApps } + If ($WindowsApps -notin @('None')) { Remove-Variable -Name WindowsApps } If ($Win32Calc.IsPresent) { $Win32Calc = ![Switch]::Present } } Else @@ -366,9 +478,16 @@ Function Optimize-Offline If ($DynamicParams.BootImage) { + $BootWimImageIndex = 0 + $BootWimImages = Get-WindowsImage -ImagePath $BootWim -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 + Foreach($Image in $BootWimImages) { + If ($Image.ImageDescription -like "Microsoft Windows Setup*") { + $BootWimImageIndex = $Image.ImageIndex + } + } Try { - $BootInfo = $BootWim | Get-ImageData -Index 2 -ErrorAction Stop + $BootInfo = $BootWim | Get-ImageData -Index $BootWimImageIndex -ErrorAction Stop } Catch { @@ -381,7 +500,7 @@ Function Optimize-Offline $MountBootParams = @{ Path = $BootMount ImagePath = $BootWim - Index = 2 + Index = $BootWimImageIndex CheckIntegrity = $true ScratchDirectory = $ScratchFolder LogPath = $DISMLog @@ -444,333 +563,656 @@ Function Optimize-Offline } #endregion Image Preparation - #region Provisioned App Package Removal - If ($WindowsApps -and (Get-AppxProvisionedPackage -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1).Count -gt 0) - { - $Host.UI.RawUI.WindowTitle = "Remove Provisioned App Packages." - $AppxPackages = Get-AppxProvisionedPackage -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Select-Object -Property DisplayName, PackageName | Sort-Object -Property DisplayName - If ($InstallInfo.Build -eq '19041') - { - $AppxPackages = $AppxPackages | ForEach-Object -Process { - $DisplayName = $PSItem.DisplayName; $PackageName = $PSItem.PackageName - If ($DisplayName -eq 'Microsoft.549981C3F5F10') { $DisplayName = 'CortanaApp.View.App' } - [PSCustomObject]@{ DisplayName = $DisplayName; PackageName = $PackageName } + + + If ($populateLists -or $populateTemplates) { + + Try { + $Items = [System.Collections.ArrayList]@( ) + $ItemsGUI = [System.Collections.ArrayList]@( ) + Get-AppxPackages -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog | ForEach-Object -Process { + [Void]$Items.Add([String]$PSItem.DisplayName) + [Void]$ItemsGUI.Add(@{ + PackageName = $PSItem.PackageName + DisplayName = $PSItem.DisplayName + Selected = $false + }) + } + ## Populate WindowsApps template + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.WindowsAppsTemplate)" + [ordered]@{ + DisplayName = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.WindowsAppsTemplate -Encoding UTF8 -Force -ErrorAction Ignore + $ItemsGUI | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.GUI.RemovalTemplates.WindowsApps -Encoding UTF8 -Force -ErrorAction Ignore + Start-Sleep 1 + If ($populateLists -and $WindowsApps -in @('Whitelist', 'Blacklist')) { + ## Populate WindowsApps selected type of list + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.WindowsAppsList)" + Start-Sleep 1 + $Items = $Items | Out-GridView -Title "Select windows apps to save to the $($WindowsApps)" -PassThru + If($Items -isnot [array]) { + $Items = @($Items) + } + [ordered]@{ + DisplayName = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.WindowsAppsList -Encoding UTF8 -Force -ErrorAction Ignore + } + + $Items = [System.Collections.ArrayList]@( ) + $ItemsGUI = [System.Collections.ArrayList]@( ) + Get-SystemPackages | ForEach-Object -Process { + [Void]$Items.Add([String]$PSItem.DisplayName) + [Void]$ItemsGUI.Add(@{ + DisplayName = $PSItem.DisplayName + Selected = $false + }) + } + ## Populate SystemApps template + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.SystemAppsTemplate)" + [ordered]@{ + DisplayName = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.SystemAppsTemplate -Encoding UTF8 -Force -ErrorAction Ignore + $ItemsGUI | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.GUI.RemovalTemplates.SystemApps -Encoding UTF8 -Force -ErrorAction Ignore + Start-Sleep 1 + If ($populateLists -and $SystemApps -in @('Whitelist', 'Blacklist')) { + ## Populate SystemApps selected type of list + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.SystemAppsList)" + Start-Sleep 1 + $Items = $Items | Out-GridView -Title "Select system apps to save to the $($SystemApps)" -PassThru + If($Items -isnot [array]) { + $Items = @($Items) + } + [ordered]@{ + DisplayName = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.SystemAppsList -Encoding UTF8 -Force -ErrorAction Ignore + } + + $Items = [System.Collections.ArrayList]@( ) + $ItemsGUI = [System.Collections.ArrayList]@( ) + Get-CapabilityPackages -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog | ForEach-Object -Process { + [Void]$Items.Add([String]$PSItem.Name) + [Void]$ItemsGUI.Add(@{ + Name = $PSItem.Name + Selected = $false + }) + } + ## Populate capabilities template + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.CapabilitiesTemplate)" + [ordered]@{ + Name = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.CapabilitiesTemplate -Encoding UTF8 -Force -ErrorAction Ignore + $ItemsGUI | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.GUI.RemovalTemplates.Capabilities -Encoding UTF8 -Force -ErrorAction Ignore + Start-Sleep 1 + If ($populateLists -and $Capabilities -in @('Whitelist', 'Blacklist')) { + ## Populate Capabilities selected type of list + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.CapabilitiesList)" + Start-Sleep 1 + $Items = $Items | Out-GridView -Title "Select capabilities to save to the $($Capabilities)" -PassThru + If($Items -isnot [array]) { + $Items = @($Items) + } + [ordered]@{ + Name = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.CapabilitiesList -Encoding UTF8 -Force -ErrorAction Ignore + } + + $Items = [System.Collections.ArrayList]@( ) + $ItemsGUI = [System.Collections.ArrayList]@( ) + Get-OtherWindowsPackages -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog | ForEach-Object -Process { + [Void]$Items.Add([String]$PSItem.PackageName) + [Void]$ItemsGUI.Add(@{ + PackageName = $PSItem.PackageName + Selected = $false + }) + } + # Populate Packages template + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.PackagesTemplate)" + [ordered]@{ + PackageName = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.PackagesTemplate -Encoding UTF8 -Force -ErrorAction Ignore + $ItemsGUI | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.GUI.RemovalTemplates.Packages -Encoding UTF8 -Force -ErrorAction Ignore + Start-Sleep 1 + If ($populateLists -and $Packages -in @('Whitelist', 'Blacklist')) { + ## Populate Packages selected type of list + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.PackagesList)" + Start-Sleep 1 + $Items = $Items | Out-GridView -Title "Select packages to save to the $($Packages)" -PassThru + If($Items -isnot [array]) { + $Items = @($Items) + } + [ordered]@{ + PackageName = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.PackagesList -Encoding UTF8 -Force -ErrorAction Ignore + } + + $Items = [System.Collections.ArrayList]@( ) + $ItemsGUI = [System.Collections.ArrayList]@( ) + Get-OptionalEnabledFeatures -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog | ForEach-Object -Process { + [Void]$Items.Add([String]$PSItem.FeatureName) + [Void]$ItemsGUI.Add(@{ + FeatureName = $PSItem.FeatureName + States = @("Enabled", "Disabled") + State = "Enabled" + OriginalState = "Enabled" + }) + } + ## Populate FeaturesToDisable template + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.FeaturesToDisableTemplate)" + [ordered]@{ + FeatureName = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.FeaturesToDisableTemplate -Encoding UTF8 -Force -ErrorAction Ignore + Start-Sleep 1 + If ($populateLists -and $FeaturesToDisable -eq 'List') { + ## Populate FeaturesToDisable list + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.FeaturesToDisableList)" + Start-Sleep 1 + $Items = $Items | Out-GridView -Title "Select features to disable for saving to the FeaturesToDisable list" -PassThru + If($Items -isnot [array]) { + $Items = @($Items) + } + [ordered]@{ + FeatureName = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.FeaturesToDisableList -Encoding UTF8 -Force -ErrorAction Ignore + } + + $Items = [System.Collections.ArrayList]@( ) + Get-OptionalDisabledFeatures -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog | ForEach-Object -Process { + [Void]$Items.Add([String]$PSItem.FeatureName) + [Void]$ItemsGUI.Add(@{ + FeatureName = $PSItem.FeatureName + States = @("Enabled", "Disabled") + State = "Disabled" + OriginalState = "Disabled" + }) + } + ## Populate FeaturesToEnable template + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.FeaturesToEnableTemplate)" + [ordered]@{ + FeatureName = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.FeaturesToEnableTemplate -Encoding UTF8 -Force -ErrorAction Ignore + Start-Sleep 1 + If ($populateLists -and $FeaturesToEnable -eq 'List') { + ## Populate FeaturesToEnable list + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.FeaturesToEnableList)" + Start-Sleep 1 + $Items = $Items | Out-GridView -Title "Select features to disable for saving to the FeaturesToEnable list" -PassThru + If($Items -isnot [array]) { + $Items = @($Items) + } + [ordered]@{ + FeatureName = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.FeaturesToEnableList -Encoding UTF8 -Force -ErrorAction Ignore } + $ItemsGUI | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.GUI.RemovalTemplates.Features -Encoding UTF8 -Force -ErrorAction Ignore + + RegHives -Load + $Items = Get-ImageServices + $ItemsGUI = [System.Collections.ArrayList]@( ) + $Items | ForEach-Object -Process { + [Void]$ItemsGUI.Add(@{ + Name = [String]$PSItem.name + Description = $PSItem.description + OriginalStart = $PSItem.startLabel + Start = $PSItem.startLabel + Starts = $OptimizeOffline.ServicesStartLabels + }) + } + $JsonInfo = $OptimizeOffline.ServicesStartLabels | ForEach-Object -Process { + "$($OptimizeOffline.ServicesStartLabels.IndexOf($_)) = $_" + } + ## Populate Services template + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists.ServicesTemplate)" + [ordered]@{ + __Info = $JsonInfo + Services = $Items + } | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.ServicesTemplate -Encoding UTF8 -Force -ErrorAction Ignore + $ItemsGUI | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.GUI.RemovalTemplates.Services -Encoding UTF8 -Force -ErrorAction Ignore + If ($populateLists -and $Services -in @('List', 'Advanced')) { + Log "$($OptimizeData.Populating) $($OptimizeOffline.Lists."Services$($Services)")" + Start-Sleep 1 + $Items = $Items | Out-GridView -Title "Select services save to the list" -PassThru + If($Items -isnot [array]) { + $Items = @($Items) + } + $JsonData = [ordered]@{ + __Info = $JsonInfo + Services = $Items + } + if($Services -eq 'List'){ + $JsonData.Services = [System.Collections.ArrayList]@() + foreach ($Item in $Items) { + [Void]$JsonData.Services.Add($Item.name) + } + } + $JsonData | ConvertTo-Json | Out-File -FilePath $OptimizeOffline.Lists.Services$($Services) -Encoding UTF8 -Force -ErrorAction Ignore + } + RegHives -Unload + + } Catch { + Log $Error[0] + } Finally { + Dismount-Images + @($TempDirectory, $DISMLog, $(GetPath -Path $Env:SystemRoot -Child 'Logs\DISM\dism.log')) | Purge -ErrorAction Ignore } - $RemovedAppxPackages = [Collections.Hashtable]::New() - Switch ($PSBoundParameters.WindowsApps) + Return + } + + + #region Provisioned App Package Removal + $RemovedPackages = [Collections.Hashtable]::New(); + $AppxPackages = Get-AppxPackages -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog + If ($WindowsApps -in $AllowedRemovalOptions) + { + Try { - 'Select' + $Host.UI.RawUI.WindowTitle = "Remove Provisioned App Packages." + + $appsToRemove = [System.Collections.ArrayList]@() + + $RemovedAppxPackages = [Collections.Hashtable]::New() + Switch ($PSBoundParameters.WindowsApps) { - Try - { - $AppxPackages | Out-GridView -Title "Select the Provisioned App Packages to Remove." -PassThru | ForEach-Object -Process { - $RemoveAppxParams = @{ - Path = $InstallMount - PackageName = $PSItem.PackageName - ScratchDirectory = $ScratchFolder - LogPath = $DISMLog - LogLevel = 1 - ErrorAction = 'Stop' - } - Log ($OptimizeData.RemovingWindowsApp -f $PSItem.DisplayName) - [Void](Remove-AppxProvisionedPackage @RemoveAppxParams) - $RemovedAppxPackages.Add($PSItem.DisplayName, $PSItem.PackageName) - } - $DynamicParams.WindowsApps = $true - } - Catch + 'Select' { - Log $OptimizeData.FailedRemovingWindowsApps -Type Error -ErrorRecord $Error[0] - Stop-Optimize + $appsToRemove = $AppxPackages | Out-GridView -Title "Select the Provisioned App Packages to Remove." -PassThru + Break } - Break - } - 'Whitelist' - { - If (Test-Path -Path $OptimizeOffline.AppxWhitelist) + 'Whitelist' { - Try + If (Test-Path -Path $OptimizeOffline.Lists.WindowsAppsList) { - If ($InstallInfo.Build -eq '19041') - { - $WhitelistJSON = Get-Content -Path $OptimizeOffline.AppxWhitelist -Raw -ErrorAction Stop - If ($WhitelistJSON.Contains('Microsoft.549981C3F5F10')) { $WhitelistJSON = $WhitelistJSON.Replace('Microsoft.549981C3F5F10', 'CortanaApp.View.App') } - $WhitelistJSON = $WhitelistJSON | ConvertFrom-Json -ErrorAction Stop - } - Else - { - $WhitelistJSON = Get-Content -Path $OptimizeOffline.AppxWhitelist -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop - } + $AppsJson = Get-Content -Path $OptimizeOffline.Lists.WindowsAppsList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop | Select-Object -ExpandProperty DisplayName + $AppxPackages | ForEach-Object -Process { - If ($PSItem.DisplayName -notin $WhitelistJSON.DisplayName) - { - $RemoveAppxParams = @{ - Path = $InstallMount - PackageName = $PSItem.PackageName - ScratchDirectory = $ScratchFolder - LogPath = $DISMLog - LogLevel = 1 - ErrorAction = 'Stop' + $ToRemove = $true + Foreach($App in $AppsJson){ + If ($PSItem.DisplayName -eq $App -or ($App -Match "\*" -and $PSItem.DisplayName -like $App)) + { + $ToRemove = $false + Break } - Log ($OptimizeData.RemovingWindowsApp -f $PSItem.DisplayName) - [Void](Remove-AppxProvisionedPackage @RemoveAppxParams) - $RemovedAppxPackages.Add($PSItem.DisplayName, $PSItem.PackageName) + } + If($ToRemove){ + [void]$appsToRemove.Add($PSItem) } } - $DynamicParams.WindowsApps = $true - } - Catch - { - Log $OptimizeData.FailedRemovingWindowsApps -Type Error -ErrorRecord $Error[0] - Stop-Optimize } + Break } - Break - } - 'All' - { - Try + 'Blacklist' { - $AppxPackages | ForEach-Object -Process { - $RemoveAppxParams = @{ - Path = $InstallMount - PackageName = $PSItem.PackageName - ScratchDirectory = $ScratchFolder - LogPath = $DISMLog - LogLevel = 1 - ErrorAction = 'Stop' + If (Test-Path -Path $OptimizeOffline.Lists.WindowsAppsList) + { + $AppsJson = Get-Content -Path $OptimizeOffline.Lists.WindowsAppsList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop | Select-Object -ExpandProperty DisplayName + + $AppxPackages | ForEach-Object -Process { + Foreach($App in $AppsJson){ + If ($PSItem.DisplayName -eq $App -or ($App -Match "\*" -and $PSItem.DisplayName -like $App)) + { + [void]$appsToRemove.Add($PSItem) + Break + } + } } - Log ($OptimizeData.RemovingWindowsApp -f $PSItem.DisplayName) - [Void](Remove-AppxProvisionedPackage @RemoveAppxParams) - $RemovedAppxPackages.Add($PSItem.DisplayName, $PSItem.PackageName) } - $DynamicParams.WindowsApps = $true + Break } - Catch + 'All' { - Log $OptimizeData.FailedRemovingWindowsApps -Type Error -ErrorRecord $Error[0] - Stop-Optimize + $appsToRemove = $AppxPackages + Break } - Break } + $appsToRemove | ForEach-Object -Process { + $RemoveAppxParams = @{ + Path = $InstallMount + PackageName = $PSItem.PackageName + ScratchDirectory = $ScratchFolder + LogPath = $DISMLog + LogLevel = 1 + ErrorAction = 'Stop' + } + Log ($OptimizeData.RemovingWindowsApp -f $PSItem.DisplayName) + If ($PSItem.DisplayName -notin @("Microsoft.SecHealthUI") -or [System.Environment]::OSVersion.Version.Build -lt '22000'){ + [Void](Remove-AppxProvisionedPackage @RemoveAppxParams) + } + $RemovedAppxPackages.Add($PSItem.DisplayName, $PSItem.PackageName) + $RemovedPackages.Add($PSItem.DisplayName, $PSItem.PackageName) + } + $DynamicParams.WindowsApps = $($appsToRemove.Count -gt 0) + } + Catch + { + Log $OptimizeData.FailedRemovingWindowsApps -Type Error -ErrorRecord $Error[0] + Stop-Optimize } $Host.UI.RawUI.WindowTitle = $null; Clear-Host } + $AppxPackages = Get-AppxPackages -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog #endregion Provisioned App Package Removal #region System App Removal - If ($SystemApps.IsPresent) + If ($SystemApps -in $AllowedRemovalOptions) { Clear-Host $Host.UI.RawUI.WindowTitle = "Remove System Apps." - $PSCmdlet.WriteWarning($OptimizeData.SystemAppsWarning) + Start-Sleep 5 + $InboxAppsKey = "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications" + + $InboxAppsPackages = Get-SystemPackages + RegHives -Load - $InboxAppsPackages = Get-ChildItem -Path $InboxAppsKey -Name | ForEach-Object -Process { - $DisplayName = $PSItem.Split('_')[0]; $PackageName = $PSItem - If ($DisplayName -like '1527c705-839a-4832-9118-54d4Bd6a0c89') { $DisplayName = 'Microsoft.Windows.FilePicker' } - If ($DisplayName -like 'c5e2524a-ea46-4f67-841f-6a9465d9d515') { $DisplayName = 'Microsoft.Windows.FileExplorer' } - If ($DisplayName -like 'E2A4F912-2574-4A75-9BB0-0D023378592B') { $DisplayName = 'Microsoft.Windows.AppResolverUX' } - If ($DisplayName -like 'F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE') { $DisplayName = 'Microsoft.Windows.AddSuggestedFoldersToLibarayDialog' } - [PSCustomObject]@{ DisplayName = $DisplayName; PackageName = $PackageName } - } | Sort-Object -Property DisplayName | Out-GridView -Title "Remove System Apps." -PassThru + If ($InboxAppsPackages) { - Clear-Host $RemovedSystemApps = [Collections.Hashtable]::New() - Try - { - $InboxAppsPackages | ForEach-Object -Process { + + $packagesToRemove = [System.Collections.ArrayList]@() + + Try { + + Switch ($PSBoundParameters.SystemApps) + { + 'Select' + { + + $PSCmdlet.WriteWarning($OptimizeData.SystemAppsWarning) + + $packagesToRemove = $InboxAppsPackages | Out-GridView -Title "Remove System Apps." -PassThru + + Break + } + 'Whitelist' + { + If (Test-Path -Path $OptimizeOffline.Lists.SystemAppsList) + { + $SystemAppsJson = Get-Content -Path $OptimizeOffline.Lists.SystemAppsList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop | Select-Object -ExpandProperty DisplayName + $InboxAppsPackages | ForEach-Object -Process { + $ToRemove = $true + Foreach($SystemApp in $SystemAppsJson){ + If ($PSItem.DisplayName -eq $SystemApp -or ($SystemApp -Match "\*" -and $PSItem.DisplayName -like $SystemApp)) + { + $ToRemove = $false + Break + } + } + If($ToRemove){ + [void]$packagesToRemove.Add($PSItem) + } + } + } + Break + } + 'Blacklist' + { + If (Test-Path -Path $OptimizeOffline.Lists.SystemAppsList) + { + $SystemAppsJson = Get-Content -Path $OptimizeOffline.Lists.SystemAppsList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop | Select-Object -ExpandProperty DisplayName + $InboxAppsPackages | ForEach-Object -Process { + Foreach($SystemApp in $SystemAppsJson){ + If ($PSItem.DisplayName -eq $SystemApp -or ($SystemApp -Match "\*" -and $PSItem.DisplayName -like $SystemApp)) + { + [void]$packagesToRemove.Add($PSItem) + Break + } + } + } + } + Break + } + 'All' + { + $packagesToRemove = $InboxAppsPackages + } + } + + $packagesToRemove | ForEach-Object -Process { $PackageKey = (GetPath -Path $InboxAppsKey -Child $PSItem.PackageName) -replace 'HKLM:', 'HKLM' Log ($OptimizeData.RemovingSystemApp -f $PSItem.DisplayName) $RET = StartExe $REG -Arguments ('DELETE "{0}" /F' -f $PackageKey) -ErrorAction Stop If ($RET -eq 1) { Log ($OptimizeData.FailedRemovingSystemApp -f $PSItem.DisplayName) -Type Error; Continue } $RemovedSystemApps.Add($PSItem.DisplayName, $PSItem.PackageName) - Start-Sleep 2 + $RemovedPackages.Add($PSItem.DisplayName, $PSItem.PackageName) + Start-Sleep 1 } - $DynamicParams.SystemApps = $true - } - Catch - { + + $DynamicParams.SystemApps = $($packagesToRemove.Count -gt 0) + } Catch { Log $OptimizeData.FailedRemovingSystemApps -Type Error -ErrorRecord $Error[0] Stop-Optimize } - Finally - { - RegHives -Unload - } } + RegHives -Unload $Host.UI.RawUI.WindowTitle = $null; Clear-Host } #endregion System App Removal + $DynamicParams.RemovedPackages = $RemovedPackages; + #region Removed Package Clean-up - If ($DynamicParams.WindowsApps -or $DynamicParams.SystemApps) + If ($DynamicParams.WindowsApps) { - Log $OptimizeData.RemovedPackageCleanup - If ($DynamicParams.WindowsApps) + If ($InstallInfo.Build -lt '19041') { - If ($InstallInfo.Build -lt '19041') - { - If ((Get-AppxProvisionedPackage -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1).Count -eq 0) { Get-ChildItem -Path (GetPath -Path $InstallMount -Child 'Program Files\WindowsApps') -Force | Purge -Force } - Else { Get-ChildItem -Path (GetPath -Path $InstallMount -Child 'Program Files\WindowsApps') -Force | Where-Object -Property Name -In $RemovedAppxPackages.Values | Purge -Force } - } - Else - { - If ((Get-AppxProvisionedPackage -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1).Count -eq 0) { Get-ChildItem -Path (GetPath -Path $InstallMount -Child 'Program Files\WindowsApps') -Force | Purge -Force } - } + If ($AppxPackages.Count -eq 0) { Get-ChildItem -Path (GetPath -Path $InstallMount -Child 'Program Files\WindowsApps') -Force | Purge -Force } + Else { Get-ChildItem -Path (GetPath -Path $InstallMount -Child 'Program Files\WindowsApps') -Force | Where-Object -Property Name -In $RemovedAppxPackages.Values | Purge -Force } } - RegHives -Load - $Visibility = [Text.StringBuilder]::New('hide:') - If ($RemovedAppxPackages.'Microsoft.WindowsMaps') - { - RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\Maps" -Name "AutoUpdateEnabled" -Value 0 -Type DWord - If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\MapsBroker") { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\MapsBroker" -Name "Start" -Value 4 -Type DWord } - [Void]$Visibility.Append('maps;maps-downloadmaps;') - } - If ($RemovedAppxPackages.'Microsoft.Wallet' -and (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\WalletService")) { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\WalletService" -Name "Start" -Value 4 -Type DWord } - If ($RemovedAppxPackages.'Microsoft.XboxIdentityProvider' -and ($RemovedAppxPackages.Keys -like "*Xbox*").Count -gt 1 -or $RemovedSystemApps.'Microsoft.XboxGameCallableUI') - { - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\GameDVR" -Name "AllowGameDVR" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\GameDVR" -Name "AppCaptureEnabled" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\GameDVR" -Name "AudioCaptureEnabled" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\GameDVR" -Name "CursorCaptureEnabled" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\GameBar" -Name "AutoGameModeEnabled" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\GameBar" -Name "AllowAutoGameMode" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\GameBar" -Name "UseNexusForGameBarEnabled" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\GameBar" -Name "ShowStartupPanel" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\System\GameConfigStore" -Name "GameDVR_Enabled" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\System\GameConfigStore" -Name "GameDVR_FSEBehavior" -Value 2 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\System\GameConfigStore" -Name "GameDVR_FSEBehaviorMode" -Value 2 -Type DWord - @("xbgm", "XblAuthManager", "XblGameSave", "xboxgip", "XboxGipSvc", "XboxNetApiSvc") | ForEach-Object -Process { If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem)") { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem)" -Name "Start" -Value 4 -Type DWord } } - [Void]$Visibility.Append('gaming-gamebar;gaming-gamedvr;gaming-broadcasting;gaming-gamemode;gaming-xboxnetworking;quietmomentsgame;') - If ($InstallInfo.Build -lt '17763') { [Void]$Visibility.Append('gaming-trueplay;') } - } - If ($RemovedAppxPackages.'Microsoft.YourPhone' -or $RemovedSystemApps.'Microsoft.Windows.CallingShellApp') - { - [Void]$Visibility.Append('mobile-devices;mobile-devices-addphone;mobile-devices-addphone-direct;') - If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\PhoneSvc") { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\PhoneSvc" -Name "Start" -Value 4 -Type DWord } - } - If ($RemovedSystemApps.'Microsoft.MicrosoftEdge' -and !$MicrosoftEdge.IsPresent) { RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\EdgeUpdate" -Name "DoNotUpdateToEdgeWithChromium" -Value 1 -Type DWord } - If ($RemovedSystemApps.'Microsoft.BioEnrollment') - { - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Biometrics" -Name "Enabled" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Biometrics\Credential Provider" -Name "Enabled" -Value 0 -Type DWord - If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\WbioSrvc") { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\WbioSrvc" -Name "Start" -Value 4 -Type DWord } - $DynamicParams.BioEnrollment = $true - } - If ($RemovedSystemApps.'Microsoft.Windows.SecureAssessmentBrowser') - { - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\SecureAssessment" -Name "AllowScreenMonitoring" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\SecureAssessment" -Name "AllowTextSuggestions" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\SecureAssessment" -Name "RequirePrinting" -Value 0 -Type DWord - } - If ($RemovedSystemApps.'Microsoft.Windows.ContentDeliveryManager') - { - @("ContentDeliveryAllowed", "FeatureManagementEnabled", "OemPreInstalledAppsEnabled", "PreInstalledAppsEnabled", "PreInstalledAppsEverEnabled", "RotatingLockScreenEnabled", - "RotatingLockScreenOverlayEnabled", "SilentInstalledAppsEnabled", "SoftLandingEnabled", "SystemPaneSuggestionsEnabled", "SubscribedContentEnabled", - "SubscribedContent-202913Enabled", "SubscribedContent-202914Enabled", "SubscribedContent-280797Enabled", "SubscribedContent-280811Enabled", "SubscribedContent-280812Enabled", - "SubscribedContent-280813Enabled", "SubscribedContent-280814Enabled", "SubscribedContent-280815Enabled", "SubscribedContent-280810Enabled", "SubscribedContent-280817Enabled", - "SubscribedContent-310091Enabled", "SubscribedContent-310092Enabled", "SubscribedContent-310093Enabled", "SubscribedContent-310094Enabled", "SubscribedContent-314558Enabled", - "SubscribedContent-314559Enabled", "SubscribedContent-314562Enabled", "SubscribedContent-314563Enabled", "SubscribedContent-314566Enabled", "SubscribedContent-314567Enabled", - "SubscribedContent-338380Enabled", "SubscribedContent-338387Enabled", "SubscribedContent-338381Enabled", "SubscribedContent-338388Enabled", "SubscribedContent-338382Enabled", - "SubscribedContent-338389Enabled", "SubscribedContent-338386Enabled", "SubscribedContent-338393Enabled", "SubscribedContent-346480Enabled", "SubscribedContent-346481Enabled", - "SubscribedContent-353694Enabled", "SubscribedContent-353695Enabled", "SubscribedContent-353696Enabled", "SubscribedContent-353697Enabled", "SubscribedContent-353698Enabled", - "SubscribedContent-353699Enabled", "SubscribedContent-88000044Enabled", "SubscribedContent-88000045Enabled", "SubscribedContent-88000105Enabled", "SubscribedContent-88000106Enabled", - "SubscribedContent-88000161Enabled", "SubscribedContent-88000162Enabled", "SubscribedContent-88000163Enabled", "SubscribedContent-88000164Enabled", "SubscribedContent-88000165Enabled", - "SubscribedContent-88000166Enabled") | ForEach-Object -Process { RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name $PSItem -Value 0 -Type DWord } - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableWindowsConsumerFeatures" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Policies\Microsoft\Microsoft\Windows\CurrentVersion\PushNotifications" -Name "NoCloudApplicationNotification" -Value 1 -Type DWord - } - If ($RemovedSystemApps.'Microsoft.Windows.SecHealthUI') - { - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender" -Name "DisableAntiSpyware" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Spynet" -Name "SpyNetReporting" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Spynet" -Name "SubmitSamplesConsent" -Value 2 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\MpEngine" -Name "MpEnablePus" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Reporting" -Name "DisableEnhancedNotifications" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" -Name "DisableBehaviorMonitoring" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" -Name "DisableRealtimeMonitoring" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" -Name "DisableOnAccessProtection" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" -Name "DisableScanOnRealtimeEnable" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" -Name "DisableIOAVProtection" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Policy Manager" -Name "AllowBehaviorMonitoring" -Value 2 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Policy Manager" -Name "AllowCloudProtection" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Policy Manager" -Name "AllowRealtimeMonitoring" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Policy Manager" -Name "SubmitSamplesConsent" -Value 2 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\UX Configuration" -Name "Notification_Suppress" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\MRT" -Name "DontOfferThroughWUAU" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\MRT" -Name "DontReportInfectionInformation" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender Security Center\Systray" -Name "HideSystray" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows Defender\Features" -Name "TamperProtection" -Value 0 -Type DWord -Force - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows Security Health\State" -Name "AccountProtection_MicrosoftAccount_Disconnected" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows Security Health\State" -Name "AppAndBrowser_EdgeSmartScreenOff" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\AppHost" -Name "SmartScreenEnabled" -Value "Off" -Type String - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer" -Name "SmartScreenEnabled" -Value "Off" -Type String - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Explorer" -Name "SmartScreenEnabled" -Value "Off" -Type String - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost" -Name "EnableWebContentEvaluation" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\AppHost" -Name "EnableWebContentEvaluation" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\System" -Name "EnableSmartScreen" -Value 0 -Type DWord - @("SecurityHealthService", "WinDefend", "WdNisSvc", "WdNisDrv", "WdBoot", "WdFilter", "Sense") | ForEach-Object -Process { If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem)") { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem)" -Name "Start" -Value 4 -Type DWord } } - @("HKLM:\WIM_HKLM_SOFTWARE\Classes\*\shellex\ContextMenuHandlers\EPP", "HKLM:\WIM_HKLM_SOFTWARE\Classes\Directory\shellex\ContextMenuHandlers\EPP", "HKLM:\WIM_HKLM_SOFTWARE\Classes\Drive\shellex\ContextMenuHandlers\EPP", - "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Control\WMI\AutoLogger\DefenderApiLogger", "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Control\WMI\AutoLogger\DefenderAuditLogger") | Purge - Remove-KeyProperty -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\Run" -Name "SecurityHealth" - If (!$DynamicParams.LTSC -or $MicrosoftEdge.IsPresent) - { - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\MicrosoftEdge\PhishingFilter" -Name "EnabledV9" -Value 0 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\WOW6432Node\Policies\Microsoft\MicrosoftEdge\PhishingFilter" -Name "EnabledV9" -Value 0 -Type DWord - } - If ($InstallInfo.Build -ge '17763') - { - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\SmartScreen" -Name "ConfigureAppInstallControlEnabled" -Value 1 -Type DWord - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\SmartScreen" -Name "ConfigureAppInstallControl" -Value "Anywhere" -Type String - } - [Void]$Visibility.Append('windowsdefender;') - $DynamicParams.SecHealthUI = $true - } - If ($Visibility.Length -gt 5) - { - RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "SettingsPageVisibility" -Value $Visibility.ToString().TrimEnd(';') -Type String - RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "SettingsPageVisibility" -Value $Visibility.ToString().TrimEnd(';') -Type String + Else + { + If ($AppxPackages.Count -eq 0) { Get-ChildItem -Path (GetPath -Path $InstallMount -Child 'Program Files\WindowsApps') -Force | Purge -Force } } - RegHives -Unload - If ($DynamicParams.BioEnrollment -and (Get-WindowsCapability -Path $InstallMount -Name *Hello* -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property State -EQ Installed)) + } + RegHives -Load + $Visibility = [Text.StringBuilder]::New('hide:') + If ($RemovedPackages.'Microsoft.WindowsMaps' -or ($AppxPackages | Where-Object {$_.DisplayName -eq "Microsoft.WindowsMaps"}).Count -eq 0) + { + Log "Applying Windows Maps removal tweak" + Start-Sleep 1 + RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\Maps" -Name "AutoUpdateEnabled" -Value 0 -Type DWord + If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\MapsBroker") { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\MapsBroker" -Name "Start" -Value 4 -Type DWord } + [Void]$Visibility.Append('maps;maps-downloadmaps;') + } + If (($RemovedPackages.'Microsoft.Wallet' -or ($AppxPackages | Where-Object {$_.DisplayName -eq "Microsoft.Wallet"}).Count -eq 0) -and (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\WalletService")) { + Log "Applying Microsoft Wallet removal tweak" + Start-Sleep 1 + RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\WalletService" -Name "Start" -Value 4 -Type DWord + } + If (($RemovedPackages.'Microsoft.XboxIdentityProvider' -and ($RemovedPackages.Keys -like "*Xbox*").Count -gt 1 -or $RemovedPackages.'Microsoft.XboxGameCallableUI') -or ($AppxPackages | Where-Object {$_.DisplayName -like "*Xbox*"}).Count -eq 0) + { + Log "Applying Xbox apps removal tweak" + Start-Sleep 1 + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\GameDVR" -Name "AllowGameDVR" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\GameDVR" -Name "AppCaptureEnabled" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\GameDVR" -Name "AudioCaptureEnabled" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\GameDVR" -Name "CursorCaptureEnabled" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\GameBar" -Name "AutoGameModeEnabled" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\GameBar" -Name "AllowAutoGameMode" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\GameBar" -Name "UseNexusForGameBarEnabled" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\GameBar" -Name "ShowStartupPanel" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\System\GameConfigStore" -Name "GameDVR_Enabled" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\System\GameConfigStore" -Name "GameDVR_FSEBehavior" -Value 2 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\System\GameConfigStore" -Name "GameDVR_FSEBehaviorMode" -Value 2 -Type DWord + @("xbgm", "XblAuthManager", "XblGameSave", "xboxgip", "XboxGipSvc", "XboxNetApiSvc") | ForEach-Object -Process { If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem)") { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem)" -Name "Start" -Value 4 -Type DWord } } + [Void]$Visibility.Append('gaming-gamebar;gaming-gamedvr;gaming-broadcasting;gaming-gamemode;gaming-xboxnetworking;quietmomentsgame;') + If ($InstallInfo.Build -lt '17763') { [Void]$Visibility.Append('gaming-trueplay;') } + } + If ($RemovedPackages.'Microsoft.YourPhone' -or $RemovedPackages.'Microsoft.Windows.CallingShellApp' -or $($AppxPackages | Where-Object {$_.DisplayName -eq "Microsoft.YourPhone"}).Count -eq 0) + { + Log "Applying YourPhone removal tweak" + Start-Sleep 1 + [Void]$Visibility.Append('mobile-devices;mobile-devices-addphone;mobile-devices-addphone-direct;') + If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\PhoneSvc") { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\PhoneSvc" -Name "Start" -Value 4 -Type DWord } + } + If ($RemovedPackages.'Microsoft.MicrosoftEdge' -and !$MicrosoftEdge.IsPresent) { + Log "Applying Microsoft Edge removal tweak" + Start-Sleep 1 + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\EdgeUpdate" -Name "DoNotUpdateToEdgeWithChromium" -Value 1 -Type DWord + } + If ($RemovedPackages.'Microsoft.BioEnrollment') + { + Log "Applying Microsoft BioEnrollment removal tweak" + Start-Sleep 1 + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Biometrics" -Name "Enabled" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Biometrics\Credential Provider" -Name "Enabled" -Value 0 -Type DWord + If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\WbioSrvc") { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\WbioSrvc" -Name "Start" -Value 4 -Type DWord } + [Void]$Visibility.Append('signinoptions-launchfaceenrollment;signinoptions-launchfingerprintenrollment;') + $DynamicParams.BioEnrollment = $true + } + If ($RemovedPackages.'Microsoft.Windows.SecureAssessmentBrowser') + { + Log "Applying SecureAssessmentBrowser removal tweak" + Start-Sleep 1 + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\SecureAssessment" -Name "AllowScreenMonitoring" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\SecureAssessment" -Name "AllowTextSuggestions" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\SecureAssessment" -Name "RequirePrinting" -Value 0 -Type DWord + } + If ($RemovedPackages.'Microsoft.Windows.ContentDeliveryManager' -or $SelectiveRegistry.Disable3rdPartyApps) + { + Log "Applying ContentDeliveryManager removal tweak" + Start-Sleep 1 + @("ContentDeliveryAllowed", "FeatureManagementEnabled", "OemPreInstalledAppsEnabled", "PreInstalledAppsEnabled", "PreInstalledAppsEverEnabled", "RotatingLockScreenEnabled", + "RotatingLockScreenOverlayEnabled", "SilentInstalledAppsEnabled", "SoftLandingEnabled", "SystemPaneSuggestionsEnabled", "SubscribedContentEnabled", + "SubscribedContent-202913Enabled", "SubscribedContent-202914Enabled", "SubscribedContent-280797Enabled", "SubscribedContent-280811Enabled", "SubscribedContent-280812Enabled", + "SubscribedContent-280813Enabled", "SubscribedContent-280814Enabled", "SubscribedContent-280815Enabled", "SubscribedContent-280810Enabled", "SubscribedContent-280817Enabled", + "SubscribedContent-310091Enabled", "SubscribedContent-310092Enabled", "SubscribedContent-310093Enabled", "SubscribedContent-310094Enabled", "SubscribedContent-314558Enabled", + "SubscribedContent-314559Enabled", "SubscribedContent-314562Enabled", "SubscribedContent-314563Enabled", "SubscribedContent-314566Enabled", "SubscribedContent-314567Enabled", + "SubscribedContent-338380Enabled", "SubscribedContent-338387Enabled", "SubscribedContent-338381Enabled", "SubscribedContent-338388Enabled", "SubscribedContent-338382Enabled", + "SubscribedContent-338389Enabled", "SubscribedContent-338386Enabled", "SubscribedContent-338393Enabled", "SubscribedContent-346480Enabled", "SubscribedContent-346481Enabled", + "SubscribedContent-353694Enabled", "SubscribedContent-353695Enabled", "SubscribedContent-353696Enabled", "SubscribedContent-353697Enabled", "SubscribedContent-353698Enabled", + "SubscribedContent-353699Enabled", "SubscribedContent-88000044Enabled", "SubscribedContent-88000045Enabled", "SubscribedContent-88000105Enabled", "SubscribedContent-88000106Enabled", + "SubscribedContent-88000161Enabled", "SubscribedContent-88000162Enabled", "SubscribedContent-88000163Enabled", "SubscribedContent-88000164Enabled", "SubscribedContent-88000165Enabled", + "SubscribedContent-88000166Enabled") | ForEach-Object -Process { RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name $PSItem -Value 0 -Type DWord } + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableWindowsConsumerFeatures" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Policies\Microsoft\Microsoft\Windows\CurrentVersion\PushNotifications" -Name "NoCloudApplicationNotification" -Value 1 -Type DWord + + If ($InstallInfo.Build -ge "22000") { + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\PolicyManager\current\device\Start" -Name "ConfigureStartPins" -Type String -Value '{"pinnedList": [{}]}' + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\PolicyManager\current\device\Start" -Name "ConfigureStartPins_ProviderSet" -Type Dword -Value "0" + } + } + If ($DormantDefender.IsPresent -or $RemovedPackages.'Microsoft.Windows.SecHealthUI' -or $RemovedPackages.'Microsoft.SecHealthUI' -or (($AppxPackages | Where-Object {$_.DisplayName -eq 'Microsoft.SecHealthUI'}).Count -eq 0 -and $InstallInfo.Build -ge 22000)) + { + Log "Applying Defender removal tweak" + Start-Sleep 1 + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender" -Name "DisableAntiSpyware" -Value 1 -Type DWord + + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender" -Name "PUAProtection" -Value 1 -Type DWord + + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Spynet" -Name "SpyNetReporting" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Spynet" -Name "SubmitSamplesConsent" -Value 2 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\MpEngine" -Name "MpEnablePus" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Reporting" -Name "DisableEnhancedNotifications" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" -Name "DisableBehaviorMonitoring" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" -Name "DisableRealtimeMonitoring" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" -Name "DisableOnAccessProtection" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" -Name "DisableScanOnRealtimeEnable" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" -Name "DisableIOAVProtection" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Policy Manager" -Name "AllowBehaviorMonitoring" -Value 2 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Policy Manager" -Name "AllowCloudProtection" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Policy Manager" -Name "AllowRealtimeMonitoring" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\Policy Manager" -Name "SubmitSamplesConsent" -Value 2 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\UX Configuration" -Name "Notification_Suppress" -Value 1 -Type DWord + + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\UX Configuration" -Name "UILockdown" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender Security Center\Notifications" -Name "DisableNotifications" -Value 1 -Type DWord + + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\MRT" -Name "DontOfferThroughWUAU" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\MRT" -Name "DontReportInfectionInformation" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender Security Center\Systray" -Name "HideSystray" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows Defender\Features" -Name "TamperProtection" -Value 0 -Type DWord -Force + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows Security Health\State" -Name "AccountProtection_MicrosoftAccount_Disconnected" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows Security Health\State" -Name "AppAndBrowser_EdgeSmartScreenOff" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\AppHost" -Name "SmartScreenEnabled" -Value "Off" -Type String + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer" -Name "SmartScreenEnabled" -Value "Off" -Type String + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Explorer" -Name "SmartScreenEnabled" -Value "Off" -Type String + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost" -Name "EnableWebContentEvaluation" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\AppHost" -Name "EnableWebContentEvaluation" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost" -Name "PreventOverride" -Value 0 -Type DWord -Force + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\AppHost" -Name "PreventOverride" -Value 0 -Type DWord -Force + + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Edge\SmartScreenEnabled" -Name "(default)" -Value 0 -Type DWord -Force + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Edge\SmartScreenEnabled" -Name "(default)" -Value 0 -Type DWord -Force + + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Edge\SmartScreenPuaEnabled" -Name "(default)" -Value 0 -Type DWord -Force + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Edge\SmartScreenPuaEnabled" -Name "(default)" -Value 0 -Type DWord -Force + + + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\System" -Name "EnableSmartScreen" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\System" -Name "ShellSmartScreenLevel" -Value 0 -Type DWord -Force + @("SecurityHealthService", "WinDefend", "WdNisSvc", "WdNisDrv", "WdBoot", "WdFilter", "Sense", "webthreatdefsvc", "webthreatdefusersvc") | ForEach-Object -Process { If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem)") { RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem)" -Name "Start" -Value 4 -Type DWord } } + @("HKLM:\WIM_HKLM_SOFTWARE\Classes\*\shellex\ContextMenuHandlers\EPP", "HKLM:\WIM_HKLM_SOFTWARE\Classes\Directory\shellex\ContextMenuHandlers\EPP", "HKLM:\WIM_HKLM_SOFTWARE\Classes\Drive\shellex\ContextMenuHandlers\EPP", + "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Control\WMI\AutoLogger\DefenderApiLogger", "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Control\WMI\AutoLogger\DefenderAuditLogger") | Purge + Remove-KeyProperty -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\Run" -Name "SecurityHealth" + If (!$DynamicParams.LTSC -or $MicrosoftEdge.IsPresent -or $InstallInfo.Build -ge 22000) { - Try - { - Log $OptimizeData.RemovingBiometricCapability - [Void](Get-WindowsCapability -Path $InstallMount -Name *Hello* -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property State -EQ Installed | Remove-WindowsCapability -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 -ErrorAction Stop) - } - Catch - { - Log $OptimizeData.FailedRemovingBiometricCapability -Type Error -ErrorRecord $Error[0] - Start-Sleep 3 - } + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\MicrosoftEdge\PhishingFilter" -Name "EnabledV9" -Value 0 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\WOW6432Node\Policies\Microsoft\MicrosoftEdge\PhishingFilter" -Name "EnabledV9" -Value 0 -Type DWord } - If ($DynamicParams.SecHealthUI -and (Get-WindowsOptionalFeature -Path $InstallMount -FeatureName Windows-Defender-Default-Definitions -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property State -EQ Enabled)) + If ($InstallInfo.Build -ge '17763') { - Try - { - $DisableDefenderOptionalFeature = @{ + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\SmartScreen" -Name "ConfigureAppInstallControlEnabled" -Value 1 -Type DWord + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows Defender\SmartScreen" -Name "ConfigureAppInstallControl" -Value "Anywhere" -Type String + } + [Void]$Visibility.Append('windowsdefender;') + $DynamicParams.SecHealthUI = $true + Log $OptimizeData.DisableDefender + Clear-Host + } + If ($Visibility.Length -gt 5) + { + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "SettingsPageVisibility" -Value $Visibility.ToString().TrimEnd(';') -Type String + RegKey -Path "HKLM:\WIM_HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "SettingsPageVisibility" -Value $Visibility.ToString().TrimEnd(';') -Type String + } + If($RemovedPackages."Microsoft.Windows.Search") { + $DynamicParams.RemovedWindowsSearchPackage = $true + } + RegHives -Unload + If ($DynamicParams.BioEnrollment -and (Get-WindowsCapability -Path $InstallMount -Name *Hello* -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property State -EQ Installed)) + { + Try + { + Get-WindowsCapability -Path $InstallMount -Name *Hello* -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property State -EQ Installed | ForEach-Object -Process { + $RemoveBiometricCapability = @{ Path = $InstallMount - FeatureName = 'Windows-Defender-Default-Definitions' - Remove = $true - NoRestart = $true + Name = $PSItem.Name ScratchDirectory = $ScratchFolder LogPath = $DISMLog LogLevel = 1 ErrorAction = 'Stop' } - Log $OptimizeData.DisablingDefenderOptionalFeature - [Void](Disable-WindowsOptionalFeature @DisableDefenderOptionalFeature) + Log ($OptimizeData.RemovingBiometricCapability -f $PSItem.Name) + [Void](Remove-WindowsCapability @RemoveBiometricCapability) } - Catch - { - Log $OptimizeData.FailedDisablingDefenderOptionalFeature -Type Error -ErrorRecord $Error[0] - Start-Sleep 3 + } + Catch + { + Log $OptimizeData.FailedRemovingBiometricCapability -Type Error -ErrorRecord $Error[0] + Start-Sleep 3 + } + } + If ($DynamicParams.SecHealthUI -and (Get-WindowsOptionalFeature -Path $InstallMount -FeatureName Windows-Defender-Default-Definitions -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property State -EQ Enabled)) + { + Try + { + $DisableDefenderOptionalFeature = @{ + Path = $InstallMount + FeatureName = 'Windows-Defender-Default-Definitions' + Remove = $true + NoRestart = $true + ScratchDirectory = $ScratchFolder + LogPath = $DISMLog + LogLevel = 1 + ErrorAction = 'Stop' } + Log $OptimizeData.DisablingDefenderOptionalFeature + [Void](Disable-WindowsOptionalFeature @DisableDefenderOptionalFeature) + } + Catch + { + Log $OptimizeData.FailedDisablingDefenderOptionalFeature -Type Error -ErrorRecord $Error[0] + Start-Sleep 3 } } #endregion Removed Package Clean-up @@ -785,16 +1227,72 @@ Function Optimize-Offline #endregion Import Custom App Associations #region Windows Capability and Cabinet File Package Removal - If ($Capabilities.IsPresent) + If ($Capabilities -in $AllowedRemovalOptions) { Clear-Host $Host.UI.RawUI.WindowTitle = "Remove Windows Capabilities." - $WindowsCapabilities = Get-WindowsCapability -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object { $PSItem.Name -notlike "*Language.Basic*" -and $PSItem.Name -notlike "*TextToSpeech*" -and $PSItem.State -eq 'Installed' } | Select-Object -Property Name, State | Sort-Object -Property Name | Out-GridView -Title "Remove Windows Capabilities." -PassThru + $WindowsCapabilities = Get-CapabilityPackages -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog + If ($WindowsCapabilities) { Try { - $WindowsCapabilities | ForEach-Object -Process { + + $capabilitiesToRemove = [System.Collections.ArrayList]@() + + Switch ($PSBoundParameters.Capabilities) + { + 'Select' + { + $capabilitiesToRemove = $WindowsCapabilities | Out-GridView -Title "Remove Windows Capabilities." -PassThru + + Break + } + 'Whitelist' + { + If (Test-Path -Path $OptimizeOffline.Lists.CapabilitiesList) + { + $Names = Get-Content -Path $OptimizeOffline.Lists.CapabilitiesList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop | Select-Object -ExpandProperty Name + + $WindowsCapabilities | ForEach-Object -Process { + $ToRemove = $true + Foreach($Name in $Names){ + If ($PSItem.Name -eq $Name -or ($Name -match "\*" -and $PSItem.Name -like $Name)){ + $ToRemove = $false + Break + } + } + If($ToRemove){ + [void]$capabilitiesToRemove.Add($PSItem) + } + } + } + Break + } + 'Blacklist' + { + If (Test-Path -Path $OptimizeOffline.Lists.CapabilitiesList) + { + $Names = Get-Content -Path $OptimizeOffline.Lists.CapabilitiesList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop | Select-Object -ExpandProperty Name + + $WindowsCapabilities | ForEach-Object -Process { + Foreach($Name in $Names){ + If ($PSItem.Name -eq $Name -or ($Name -match "\*" -and $PSItem.Name -like $Name)){ + [void]$capabilitiesToRemove.Add($PSItem) + Break + } + } + } + } + Break + } + 'All' + { + $capabilitiesToRemove = $WindowsCapabilities + } + } + + $capabilitiesToRemove | ForEach-Object -Process { $RemoveCapabilityParams = @{ Path = $InstallMount Name = $PSItem.Name @@ -803,10 +1301,11 @@ Function Optimize-Offline LogLevel = 1 ErrorAction = 'Stop' } - Log ($OptimizeData.RemovingWindowsCapability -f $PSItem.Name.Split('~')[0]) + Log ($OptimizeData.RemovingWindowsCapability -f $PSItem.Name) [Void](Remove-WindowsCapability @RemoveCapabilityParams) } - $DynamicParams.Capabilities = $true + + $DynamicParams.Capabilities = $($capabilitiesToRemove.Count -gt 0) } Catch { @@ -817,16 +1316,74 @@ Function Optimize-Offline } } - If ($Packages.IsPresent) + If ($Packages -in $AllowedRemovalOptions) { Clear-Host $Host.UI.RawUI.WindowTitle = "Remove Windows Packages." - $WindowsPackages = Get-WindowsPackage -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object { $PSItem.ReleaseType -eq 'OnDemandPack' -or $PSItem.ReleaseType -eq 'LanguagePack' -or $PSItem.ReleaseType -eq 'FeaturePack' -and $PSItem.PackageName -notlike "*20H2Enablement*" -and $PSItem.PackageName -notlike "*LanguageFeatures-Basic*" -and $PSItem.PackageName -notlike "*LanguageFeatures-TextToSpeech*" -and $PSItem.PackageState -eq 'Installed' } | Select-Object -Property PackageName, ReleaseType | Sort-Object -Property PackageName | Out-GridView -Title "Remove Windows Packages." -PassThru + + $WindowsPackages = Get-OtherWindowsPackages -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog + If ($WindowsPackages) { + $packagesToRemove = [System.Collections.ArrayList]@() Try { - $WindowsPackages | ForEach-Object -Process { + + Switch ($PSBoundParameters.Packages) { + 'Select' + { + $packagesToRemove = $WindowsPackages | Out-GridView -Title "Remove Windows Packages." -PassThru + Break + } + 'Whitelist' + { + + If (Test-Path -Path $OptimizeOffline.Lists.PackagesList) + { + $PackageNames = Get-Content -Path $OptimizeOffline.Lists.PackagesList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop | Select-Object -ExpandProperty PackageName + + $WindowsPackages | ForEach-Object -Process { + $ToRemove = $true + Foreach($PackageName in $PackageNames){ + If ($PSItem.PackageName -eq $PackageName -or ($PackageName -Match "\*" -and $PSItem.PackageName -like $PackageName)) + { + $ToRemove = $false + Break + } + } + If($ToRemove){ + [void]$packagesToRemove.Add($PSItem) + } + } + } + Break + } + 'Blacklist' + { + + If (Test-Path -Path $OptimizeOffline.Lists.PackagesList) + { + $PackageNames = Get-Content -Path $OptimizeOffline.Lists.PackagesList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop | Select-Object -ExpandProperty PackageName + + $WindowsPackages | ForEach-Object -Process { + Foreach($PackageName in $PackageNames){ + If ($PSItem.PackageName -eq $PackageName -or ($PackageName -Match "\*" -and $PSItem.PackageName -like $PackageName)) + { + [void]$packagesToRemove.Add($PSItem) + Break + } + } + } + } + Break + } + 'All' + { + $packagesToRemove = $WindowsPackages + } + } + + $packagesToRemove | ForEach-Object -Process { $RemovePackageParams = @{ Path = $InstallMount PackageName = $PSItem.PackageName @@ -836,10 +1393,10 @@ Function Optimize-Offline LogLevel = 1 ErrorAction = 'Stop' } - Log ($OptimizeData.RemovingWindowsPackage -f $PSItem.PackageName.Replace('Package', $null).Split('~')[0].TrimEnd('-')) + Log ($OptimizeData.RemovingWindowsPackage -f $PSItem.PackageName) [Void](Remove-WindowsPackage @RemovePackageParams) } - $DynamicParams.Packages = $true + $DynamicParams.Packages = $($packagesToRemove.Count -gt 0) } Catch { @@ -852,9 +1409,6 @@ Function Optimize-Offline #endregion Windows Capability and Cabinet File Package Removal #region Disable Unsafe Optional Features - <# - @('SMB1Protocol', 'MicrosoftWindowsPowerShellV2Root') | ForEach-Object -Process { Get-WindowsOptionalFeature -Path $InstallMount -FeatureName $PSItem -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property State -EQ Disabled | Disable-WindowsOptionalFeature -Path $InstallMount -Remove -NoRestart -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 } - #> ForEach ($Feature In @('SMB1Protocol', 'MicrosoftWindowsPowerShellV2Root')) { If (Get-WindowsOptionalFeature -Path $InstallMount -FeatureName $Feature -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property State -EQ Enabled) @@ -884,16 +1438,46 @@ Function Optimize-Offline #endregion Disable Unsafe Optional Features #region Disable/Enable Optional Features - If ($Features.IsPresent) + If ($FeaturesToDisable -in $AllowedRemovalOptions) { Clear-Host $Host.UI.RawUI.WindowTitle = "Disable Optional Features." - $DisableFeatures = Get-WindowsOptionalFeature -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property State -EQ Enabled | Select-Object -Property FeatureName, State | Sort-Object -Property FeatureName | Out-GridView -Title "Disable Optional Features." -PassThru - If ($DisableFeatures) - { + + $EnabledFeatures = Get-OptionalEnabledFeatures -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog + + If ($EnabledFeatures) + { + $FeaturesToDisableList = [System.Collections.ArrayList]@() + Switch ($PSBoundParameters.FeaturesToDisable) { + 'Select' + { + $FeaturesToDisableList = $EnabledFeatures | Out-GridView -Title "Disable Optional Features." -PassThru + Break + } + "List" + { + If (Test-Path -Path $OptimizeOffline.Lists.FeaturesToDisableList) + { + $JSON = Get-Content -Path $OptimizeOffline.Lists.FeaturesToDisableList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop + + $EnabledFeatures | ForEach-Object -Process { + If ($PSItem.FeatureName -in $JSON.FeatureName) + { + [void]$FeaturesToDisableList.Add($PSItem) + } + } + } + + Break + } + 'All' + { + $FeaturesToDisableList = $EnabledFeatures + } + } Try { - $DisableFeatures | ForEach-Object -Process { + $FeaturesToDisableList | ForEach-Object -Process { $DisableFeatureParams = @{ Path = $InstallMount FeatureName = $PSItem.FeatureName @@ -907,7 +1491,7 @@ Function Optimize-Offline Log ($OptimizeData.DisablingOptionalFeature -f $PSItem.FeatureName) [Void](Disable-WindowsOptionalFeature @DisableFeatureParams) } - $DynamicParams.DisabledOptionalFeatures = $true + $DynamicParams.DisabledOptionalFeatures = $($FeaturesToDisableList.Count -gt 0) } Catch { @@ -916,14 +1500,50 @@ Function Optimize-Offline } $Host.UI.RawUI.WindowTitle = $null; Clear-Host } + } + if ($FeaturesToEnable -in $AllowedRemovalOptions){ Clear-Host $Host.UI.RawUI.WindowTitle = "Enable Optional Features." - $EnableFeatures = Get-WindowsOptionalFeature -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object { $PSItem.FeatureName -notlike "SMB1Protocol*" -and $PSItem.FeatureName -ne "Windows-Defender-Default-Definitions" -and $PSItem.FeatureName -notlike "MicrosoftWindowsPowerShellV2*" -and $PSItem.State -eq "Disabled" } | Select-Object -Property FeatureName, State | Sort-Object -Property FeatureName | Out-GridView -Title "Enable Optional Features." -PassThru - If ($EnableFeatures) + + $DisabledFeatures = Get-OptionalDisabledFeatures -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog + + If ($DisabledFeatures) { + + $FeaturesToEnableList = [System.Collections.ArrayList]@() + + Switch ($PSBoundParameters.FeaturesToEnable) { + 'Select' + { + $FeaturesToEnableList = $DisabledFeatures | Out-GridView -Title "Enable Optional Features." -PassThru + + Break + } + "List" + { + If (Test-Path -Path $OptimizeOffline.Lists.FeaturesToEnableList) + { + $JSON = Get-Content -Path $OptimizeOffline.Lists.FeaturesToEnableList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop + + $DisabledFeatures | ForEach-Object -Process { + If ($PSItem.FeatureName -in $JSON.FeatureName) + { + [void]$FeaturesToEnableList.Add($PSItem) + } + } + } + + Break + } + "All" + { + $FeaturesToEnableList = $DisabledFeatures + } + } + Try { - $EnableFeatures | ForEach-Object -Process { + $FeaturesToEnableList | ForEach-Object -Process { $EnableFeatureParams = @{ Path = $InstallMount FeatureName = $PSItem.FeatureName @@ -938,7 +1558,7 @@ Function Optimize-Offline Log ($OptimizeData.EnablingOptionalFeature -f $PSItem.FeatureName) [Void](Enable-WindowsOptionalFeature @EnableFeatureParams) } - $DynamicParams.EnabledOptionalFeatures = $true + $DynamicParams.EnabledOptionalFeatures = $($FeaturesToEnableList.Count -gt 0) } Catch { @@ -950,6 +1570,89 @@ Function Optimize-Offline } #endregion Disable/Enable Optional Features + #region disable windows services + if ($PSBoundParameters.Services -in $AllowedRemovalOptions){ + $ServicesToRemove = [System.Collections.ArrayList]@() + $ServicesToRemoveNames = @{} + $StartValues = @(0,1,2,3,4) + + Clear-Host + $Host.UI.RawUI.WindowTitle = $OptimizeData.ServicesModifying + + Try{ + RegHives -Load + + Switch($PSBoundParameters.Services){ + "List" + { + $JSON = Get-Content -Path $OptimizeOffline.Lists.ServicesList -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop + + $JSON.Services | ForEach-Object -Process { + If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem)") + { + $FolderKeys = Get-ItemProperty -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem)" + + If($null -ne $FolderKeys.Start){ + [void]$ServicesToRemove.Add(@{ + name = $PSItem + start = 4 + }) + } + + } + } + } + "Advanced" + { + $JSON = Get-Content -Path $OptimizeOffline.Lists.ServicesAdvanced -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop + + $JSON.Services | ForEach-Object -Process { + If (Test-Path -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem.name)") + { + $FolderKeys = Get-ItemProperty -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem.name)" + + If($null -eq $PSItem.start) { + $PSItem.start = 4 + } + + If($null -ne $FolderKeys.Start -and [int]$PSItem.start -in $StartValues){ + [void]$ServicesToRemove.Add($PSItem) + } + + } + } + } + "Select" + { + $ServicesToRemove = Get-ImageServices | Out-GridView -PassThru -Title $OptimizeData.ChooseServicesTitle + } + } + + $ServicesToRemove | ForEach-Object -Process { + $Start = If ($PSBoundParameters.Services -eq "Select") {4} Else {[Int]$PSItem.start} + Log "$($OptimizeData.ServiceModifying): $($PSItem.name), Start: $($OptimizeOffline.ServicesStartLabels[$Start])" + RegKey -Path "HKLM:\WIM_HKLM_SYSTEM\ControlSet001\Services\$($PSItem.name)" -Name "Start" -Type DWord -Value $Start + $ServicesToRemoveNames[$PSItem.name] = $Start + Start-Sleep 1 + } + $DynamicParams.DisabledWindowsServices = $($ServicesToRemove.Count -gt 0) + + # If the Delivery Optimization service has a SetState value of 'Disabled' in the Services.json file, set the delivery optimization download mode to bypass. + If ($null -ne $ServicesToRemoveNames['DoSvc'] -and $ServicesToRemoveNames['DoSvc'] -eq 4){ + Log $OptimizeData.DeliveryOptimizationBypass + RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" -Name "DODownloadMode" -Type DWord -Value 100 + Start-Sleep 1 + } + RegHives -Unload + } Catch { + Log $OptimizeData.ServicesRemovalFailed -Type Error -ErrorRecord $Error[0] + Stop-Optimize + } + + $Host.UI.RawUI.WindowTitle = $null; Clear-Host + } + #endregion disable windows services + #region DeveloperMode Integration If ($DeveloperMode.IsPresent -and (Test-Path -Path $OptimizeOffline.DevMode -Filter *DeveloperMode-Desktop-Package*.cab) -and !(Get-WindowsPackage -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property PackageName -Like *DeveloperMode*)) { @@ -978,21 +1681,27 @@ Function Optimize-Offline #endregion DeveloperMode Integration #region Windows Store Integration - If ($WindowsStore.IsPresent -and (Test-Path -Path $OptimizeOffline.WindowsStore -Filter Microsoft.WindowsStore*.appxbundle) -and !(Get-AppxProvisionedPackage -Path $InstallMount -ScratchDirectory $ScratchFolder -LogPath $DISMLog -LogLevel 1 | Where-Object -Property DisplayName -EQ Microsoft.WindowsStore)) + $DynamicParams.WindowsStore = ($AppxPackages | Where-Object -Property DisplayName -EQ Microsoft.WindowsStore) + $DynamicParams.DisableDeliveryOptimization = (!$DynamicParams.WindowsStore -and $($AppxPackages | Where-Object -Property DisplayName -eq "Microsoft.DesktopAppInstaller").Count -eq 0) + If ($WindowsStore.IsPresent -and (Test-Path -Path $OptimizeOffline.WindowsStore -Filter Microsoft.WindowsStore*.*xbundle) -and !$DynamicParams.WindowsStore) { Log $OptimizeData.IntegratingWindowsStore - $StoreBundle = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.WindowsStore*.appxbundle -File | Select-Object -ExpandProperty FullName - $PurchaseBundle = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.StorePurchaseApp*.appxbundle -File | Select-Object -ExpandProperty FullName - $XboxBundle = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.XboxIdentityProvider*.appxbundle -File | Select-Object -ExpandProperty FullName - $InstallerBundle = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.DesktopAppInstaller*.appxbundle -File | Select-Object -ExpandProperty FullName + $StoreBundle = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.WindowsStore*.*xbundle -File | Select-Object -ExpandProperty FullName + $PurchaseBundle = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.StorePurchaseApp*.*xbundle -File | Select-Object -ExpandProperty FullName + $XboxBundle = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.XboxIdentityProvider*.*xbundle -File | Select-Object -ExpandProperty FullName + $InstallerBundle = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.DesktopAppInstaller*.*xbundle -File | Select-Object -ExpandProperty FullName $StoreLicense = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.WindowsStore*.xml -File | Select-Object -ExpandProperty FullName $PurchaseLicense = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.StorePurchaseApp*.xml -File | Select-Object -ExpandProperty FullName $XboxLicense = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.XboxIdentityProvider*.xml -File | Select-Object -ExpandProperty FullName $InstallerLicense = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.DesktopAppInstaller*.xml -File | Select-Object -ExpandProperty FullName - $DependencyPackages = [Collections.Generic.List[String]]::New() - $DependencyPackages = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.VCLibs*.appx -File | Select-Object -ExpandProperty FullName - $DependencyPackages += Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter *Native.Framework*.appx -File | Select-Object -ExpandProperty FullName - $DependencyPackages += Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter *Native.Runtime*.appx -File | Select-Object -ExpandProperty FullName + + $DependencyVCLibs = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.VCLibs.140.00_*.appx -File | Select-Object -ExpandProperty FullName + $DependencyVCLibsUWPDesktop = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.VCLibs.140.00.UWPDesktop_*.appx -File | Select-Object -ExpandProperty FullName + $DependencyXAML26 = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.UI.Xaml.2.6_*.appx -File | Select-Object -ExpandProperty FullName + $DependencyXAML27 = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.UI.Xaml.2.7_*.appx -File | Select-Object -ExpandProperty FullName + $DependencyNativeFramework = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.NET.Native.Framework*.appx -File | Select-Object -ExpandProperty FullName + $DependencyNativeRuntime = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter Microsoft.NET.Native.Runtime*.appx -File | Select-Object -ExpandProperty FullName + If (!$DynamicParams.DeveloperMode) { RegHives -Load @@ -1001,6 +1710,11 @@ Function Optimize-Offline } Try { + $DependencyPackages = [Collections.Generic.List[String]]::New() + $DependencyPackages += $DependencyNativeFramework + $DependencyPackages += $DependencyNativeRuntime + $DependencyPackages += $DependencyVCLibs + $DependencyPackages += $DependencyXAML27 $StorePackage = @{ Path = $InstallMount PackagePath = $StoreBundle @@ -1012,41 +1726,60 @@ Function Optimize-Offline ErrorAction = 'Stop' } [Void](Add-AppxProvisionedPackage @StorePackage) - $PurchasePackage = @{ - Path = $InstallMount - PackagePath = $PurchaseBundle - DependencyPackagePath = $DependencyPackages - LicensePath = $PurchaseLicense - ScratchDirectory = $ScratchFolder - LogPath = $DISMLog - LogLevel = 1 - ErrorAction = 'Stop' + + If ($PurchaseBundle -and $PurchaseLicense) { + $DependencyPackages = [Collections.Generic.List[String]]::New() + $DependencyPackages += $DependencyNativeFramework + $DependencyPackages += $DependencyNativeRuntime + $DependencyPackages += $DependencyVCLibs + $PurchasePackage = @{ + Path = $InstallMount + PackagePath = $PurchaseBundle + DependencyPackagePath = $DependencyPackages + LicensePath = $PurchaseLicense + ScratchDirectory = $ScratchFolder + LogPath = $DISMLog + LogLevel = 1 + ErrorAction = 'Stop' + } + [Void](Add-AppxProvisionedPackage @PurchasePackage) } - [Void](Add-AppxProvisionedPackage @PurchasePackage) - $XboxPackage = @{ - Path = $InstallMount - PackagePath = $XboxBundle - DependencyPackagePath = $DependencyPackages - LicensePath = $XboxLicense - ScratchDirectory = $ScratchFolder - LogPath = $DISMLog - LogLevel = 1 - ErrorAction = 'Stop' + + If ($XboxBundle -and $XboxLicense) { + $DependencyPackages = [Collections.Generic.List[String]]::New() + $DependencyPackages += $DependencyNativeFramework + $DependencyPackages += $DependencyNativeRuntime + $DependencyPackages += $DependencyVCLibs + $XboxPackage = @{ + Path = $InstallMount + PackagePath = $XboxBundle + DependencyPackagePath = $DependencyPackages + LicensePath = $XboxLicense + ScratchDirectory = $ScratchFolder + LogPath = $DISMLog + LogLevel = 1 + ErrorAction = 'Stop' + } + [Void](Add-AppxProvisionedPackage @XboxPackage) } - [Void](Add-AppxProvisionedPackage @XboxPackage) - $DependencyPackages.Clear() - $DependencyPackages = Get-ChildItem -Path $OptimizeOffline.WindowsStore -Filter *Native.Runtime*.appx -File | Select-Object -ExpandProperty FullName - $InstallerPackage = @{ - Path = $InstallMount - PackagePath = $InstallerBundle - DependencyPackagePath = $DependencyPackages - LicensePath = $InstallerLicense - ScratchDirectory = $ScratchFolder - LogPath = $DISMLog - LogLevel = 1 - ErrorAction = 'Stop' + + + If ($InstallerBundle -and $InstallerLicense -and $DependencyVCLibsUWPDesktop -and $DependencyXAML26) { + $DependencyPackages = [Collections.Generic.List[String]]::New() + $DependencyPackages += $DependencyVCLibsUWPDesktop + $DependencyPackages += $DependencyXAML26 + $InstallerPackage = @{ + Path = $InstallMount + PackagePath = $InstallerBundle + DependencyPackagePath = $DependencyPackages + LicensePath = $InstallerLicense + ScratchDirectory = $ScratchFolder + LogPath = $DISMLog + LogLevel = 1 + ErrorAction = 'Stop' + } + [Void](Add-AppxProvisionedPackage @InstallerPackage) } - [Void](Add-AppxProvisionedPackage @InstallerPackage) $DynamicParams.WindowsStore = $true } Catch @@ -1164,7 +1897,7 @@ Function Optimize-Offline [IO.File]::WriteAllText((GetPath -Path $EdgeAppPath.FullName -Child master_preferences), (@' {"distribution":{"system_level":true,"do_not_create_desktop_shortcut":true,"do_not_create_quick_launch_shortcut":true,"do_not_create_taskbar_shortcut":true}} '@).Trim(), [Text.UTF8Encoding]::New($true)) - $Base64String = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes( { Get-ChildItem -Path @("HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Active Setup\Installed Components") -Recurse | Get-ItemProperty | Select-Object -Property PSPath, StubPath | Where-Object -Property StubPath -Match configure-user-settings | ForEach-Object -Process { Remove-Item -Path $PSItem.PSPath -Force }; Get-ChildItem -Path "$Env:SystemDrive\Users\*\Desktop" -Filter *lnk -Recurse | Where-Object -Property Name -Like *Edge* | Remove-Item -Force })) + $Base64String = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes({ Get-ChildItem -Path @("HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Active Setup\Installed Components") -Recurse | Get-ItemProperty | Select-Object -Property PSPath, StubPath | Where-Object -Property StubPath -Match configure-user-settings | ForEach-Object -Process { Remove-Item -Path $PSItem.PSPath -Force }; Get-ChildItem -Path "$Env:SystemDrive\Users\*\Desktop" -Filter *lnk -Recurse | Where-Object -Property Name -Like *Edge* | Remove-Item -Force })) RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -Name "EdgeCleanup" -Value "%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -EncodedCommand $Base64String" -Type ExpandString RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\EdgeUpdate" -Name "CreateDesktopShortcutDefault" -Value 0 -Type DWord RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\WOW6432Node\Policies\Microsoft\EdgeUpdate" -Name "CreateDesktopShortcutDefault" -Value 0 -Type DWord @@ -1172,6 +1905,7 @@ Function Optimize-Offline RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\WOW6432Node\Policies\Microsoft\Edge" -Name "HideFirstRunExperience" -Value 1 -Type DWord RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Edge" -Name "BackgroundModeEnabled" -Value 0 -Type DWord RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\WOW6432Node\Policies\Microsoft\Edge" -Name "BackgroundModeEnabled" -Value 0 -Type DWord + If (($InstallInfo.Build -eq '19041' -and (Get-ItemPropertyValue -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name UBR -ErrorAction Ignore) -ge 1023) -or $InstallInfo.Build -gt '19041') { RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Policies\Microsoft\Windows\Windows Feeds" -Name "EnableFeeds" -Value 0 -Type DWord } } RegHives -Unload } @@ -1298,6 +2032,7 @@ Function Optimize-Offline 17763 { 'RS5'; Break } 18362 { '19H2'; Break } 19041 { '20H1'; Break } + default { 'Insider'; Break } } If ($DaRT.Contains('Setup') -and $DynamicParams.BootImage) { @@ -1443,7 +2178,7 @@ Function Optimize-Offline } If ($Additional.RegistryTemplates -and (Test-Path -Path (GetPath -Path $OptimizeOffline.RegistryTemplates -Child *.reg))) { - Import-RegistryTemplates + Import-Registry -Path $OptimizeOffline.RegistryTemplates Start-Sleep 3 } If ($Additional.LayoutModification -and (Test-Path -Path (GetPath -Path $OptimizeOffline.LayoutModification -Child *.xml))) @@ -1463,10 +2198,29 @@ Function Optimize-Offline Start-Sleep 3 } } + If ($Additional.LayoutModification -and $InstallInfo.Build -ge "22000" -and (Test-Path -Path (GetPath -Path $OptimizeOffline.LayoutModification -Child *.json))) + { + Try + { + Log $OptimizeData.ApplyingLayoutModification + Copy-Item -Path (GetPath -Path $OptimizeOffline.LayoutModification -Child *.json) -Destination (GetPath -Path $InstallMount -Child 'Users\Default\AppData\Local\Microsoft\Windows\Shell\LayoutModification.json') -Force -ErrorAction Stop + $DynamicParams.LayoutModification = $true + } + Catch + { + Log $OptimizeData.FailedApplyingLayoutModification -Type Error -ErrorRecord $Error[0] + } + Finally + { + Start-Sleep 3 + } + } If ($Additional.Unattend -and (Test-Path -Path (GetPath -Path $OptimizeOffline.Unattend -Child unattend.xml))) { Try { + Unblock-File -Path (GetPath -Path $OptimizeOffline.Unattend -Child unattend.xml) + Log $OptimizeData.ApplyingAnswerFile $ApplyUnattendParams = @{ UnattendPath = '{0}\unattend.xml' -f $OptimizeOffline.Unattend Path = $InstallMount @@ -1475,7 +2229,6 @@ Function Optimize-Offline LogLevel = 1 ErrorAction = 'Stop' } - Log $OptimizeData.ApplyingAnswerFile [Void](Use-WindowsUnattend @ApplyUnattendParams) (GetPath -Path $InstallMount -Child 'Windows\Panther') | Create Copy-Item -Path (GetPath -Path $OptimizeOffline.Unattend -Child unattend.xml) -Destination (GetPath -Path $InstallMount -Child 'Windows\Panther') -Force @@ -1489,7 +2242,10 @@ Function Optimize-Offline } If ($Additional.Drivers) { - Get-ChildItem -Path $OptimizeOffline.Drivers -Recurse -Force | ForEach-Object -Process { $PSItem.Attributes = 0x80 } + Get-ChildItem -Path $OptimizeOffline.Drivers -Recurse -Force | ForEach-Object -Process { + Unblock-File -Path $PSItem.FullName + Set-ItemProperty -Path $PSItem.FullName -Name IsReadOnly -Value $false -ErrorAction Ignore + } If (Get-ChildItem -Path $OptimizeOffline.InstallDrivers -Include *.inf -Recurse -Force) { Try @@ -1591,22 +2347,33 @@ Function Optimize-Offline } } #endregion Additional Content Integration - + #region selective registry + Get-ChildItem -Path $OptimizeOffline.SelectiveRegistry -Filter *.ps1 -Recurse | ForEach-Object -Process { + & $_.FullName + } + #endregion selective registry + #region custom registry + If (Test-Path -Path $OptimizeOffline.CustomRegistry) + { + Import-Registry -Path $OptimizeOffline.CustomRegistry + Start-Sleep 3 + } + #endregion custom registry #region Component Store Clean-up If ($ComponentCleanup.IsPresent) { If (!(Test-Path -Path (GetPath -Path $InstallMount -Child 'Windows\WinSxS\pending.xml'))) { Log ($OptimizeData.ComponentStoreCleanup -f $InstallInfo.Name) - If ($InstallInfo.Build -ge '18362') { $RegClean = 3 } - Else { $RegClean = 0 } + If ($InstallInfo.Build -ge '18362') { $RegClean = 3 } Else { $RegClean = 0 } RegHives -Load RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide\Configuration" -Name "DisableResetbase" -Value 1 -Type DWord RegKey -Path "HKLM:\WIM_HKLM_SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide\Configuration" -Name "SupersededActions" -Value $RegClean -Type DWord RegHives -Unload + $CleanupLog = (GetPath -Path $LogFolder -Child ComponentCleanup.log) Try { - $RET = StartExe $DISM -Arguments ('/Image:"{0}" /Cleanup-Image /StartComponentCleanup /ScratchDir:"{1}" /LogPath:"{2}" /LogLevel:1' -f $InstallMount, $ScratchFolder, $DISMLog) -ErrorAction Stop + $RET = StartExe $DISM -Arguments ('/Image:"{0}" /Cleanup-Image /StartComponentCleanup /ScratchDir:"{1}" /LogPath:"{2}" /LogLevel:1' -f $InstallMount, $ScratchFolder, $CleanupLog) -ErrorAction Stop If ($RET -eq 0) { $DynamicParams.ComponentCleanup = $true } Else { Throw } } @@ -1614,6 +2381,10 @@ Function Optimize-Offline { Log ($OptimizeData.FailedComponentStoreCleanup -f $InstallInfo.Name) -Type Error } + Finally + { + $CleanupLog | Purge -ErrorAction Ignore + } } Else { @@ -1623,7 +2394,7 @@ Function Optimize-Offline #endregion Component Store Clean-up #region Start Menu Clean-up - If (!$DynamicParams.LayoutModification) + If (!$DynamicParams.LayoutModification -and $InstallInfo.Build -le '19044') { $LayoutTemplate = @" 9NBLGGH4NNS1microsoft.desktopappinstaller_8wekyb3d8bbwee1a39502-1ffc-44f0-8c28-0034168e09ff2c3f1d47-426d-c7d7-face-ef1add208818False2016-04-14T15:58:20.6111541Z2016-04-14T15:58:20.4032196Z2016-04-14T15:58:20.4032196ZFAAAAMAAAADJAAAACgAAAAMAAQAdvg9XAgDLAAAAEAAAAK/8fFGLE5YXLOpiiSIEJQrOAAAAWAAAAG0AaQBjAHIAbwBzAG8AZgB0AC4AZABlAHMAawB0AG8AcABhAHAAcABpAG4AcwB0AGEAbABsAGUAcgBfADgAdwBlAGsAeQBiADMAZAA4AGIAYgB3AGUAAADNAAAAIgAAAAEAPHRzkyJyTeprvahJYVs0C0HSgOyvT4hrOkNjQkRP3ZkgAAAABAAAABy+D1fMAAAARAAAAAEAAgBIa5/IGWUu4VPS25nTkLR8ppTVf6vcPSq/gcYDNJ9lN2zTLbFu6TvvW9vRaJ+VeOW+RRkKhoksVH7Pt7QD1r6bgFx+w8DBVQVIbEe2VcpuymyNmZ2W4wEaZRbCfq2+g9k=eLMrCQLsZziDD7p7OTk+r0/1PlW/QvNCd1tuouOIatqECfL1vw0ssHqzwztfAKlLvpaQ1NnB6MlW4wBdOziLQs6TNUNIseASPZWl9s/0qUb85+BpOoFPt+A2t0C0+1Y33UqlpBsXOLndXgySGorBjbRBEDrpX4HFrOfuyGkUSbMVFgSr0H6xXRbLJmYTId0Oy2bPCpRfTqDwqS1x71+IDSBel8I8fs6UHYdYhGvFVqiOtg2+eeuD5pd6I5wiYLIXkfzu6/66QDT7kR1LJ+zgEJCFfauUft1vUIYjTj4evPLZUXRrK7ff8ktfaoppD3o7ToN4C3XSik9HzcsEfhLeUg==oVSJXItDsaAIfwyR9bhh/ZSppCAO+in9POLWdC2/TQodgeHZzbdBvxJvKhpbrq6ZP0FsSElLwRoLAmv7zIuVw3Vb7tfQt5bjCDHRAG9fesNlYKV3ybyNrHyzglfZPRB5UJZw32yi03zQa+LLa05fjs6joEmlHc5BrGQrGrbNMBahz4cmuxKC4/dhEb7JZFUkc0MRhs/M3Ve511HQfKuG+92g1OffJdRsAPzWRdskPoN35knnqno7F85OBmGV/LNBgdtDWUH6di1eUCQFeKGfMp+Q/LFUX9jawTTEPn72tYbpYASug05Skcg6KTHlcLGzevxGw7BYsOsqfDka5n0YGw==AAEAAQ== \ No newline at end of file diff --git a/Packages/WindowsStore/Microsoft.NET.Native.Framework.2.2_2.2.27912.0_x64__8wekyb3d8bbwe.Appx b/Packages/WindowsStore/Microsoft.NET.Native.Framework.2.2_2.2.27912.0_x64__8wekyb3d8bbwe.Appx deleted file mode 100644 index 072ccf4..0000000 Binary files a/Packages/WindowsStore/Microsoft.NET.Native.Framework.2.2_2.2.27912.0_x64__8wekyb3d8bbwe.Appx and /dev/null differ diff --git a/Packages/WindowsStore/Microsoft.NET.Native.Framework.2.2_2.2.27912.0_x86__8wekyb3d8bbwe.Appx b/Packages/WindowsStore/Microsoft.NET.Native.Framework.2.2_2.2.27912.0_x86__8wekyb3d8bbwe.Appx deleted file mode 100644 index 2f3e382..0000000 Binary files a/Packages/WindowsStore/Microsoft.NET.Native.Framework.2.2_2.2.27912.0_x86__8wekyb3d8bbwe.Appx and /dev/null differ diff --git a/Packages/WindowsStore/Microsoft.NET.Native.Runtime.2.2_2.2.28604.0_x64__8wekyb3d8bbwe.Appx b/Packages/WindowsStore/Microsoft.NET.Native.Runtime.2.2_2.2.28604.0_x64__8wekyb3d8bbwe.Appx deleted file mode 100644 index e70937b..0000000 Binary files a/Packages/WindowsStore/Microsoft.NET.Native.Runtime.2.2_2.2.28604.0_x64__8wekyb3d8bbwe.Appx and /dev/null differ diff --git a/Packages/WindowsStore/Microsoft.NET.Native.Runtime.2.2_2.2.28604.0_x86__8wekyb3d8bbwe.Appx b/Packages/WindowsStore/Microsoft.NET.Native.Runtime.2.2_2.2.28604.0_x86__8wekyb3d8bbwe.Appx deleted file mode 100644 index abf125b..0000000 Binary files a/Packages/WindowsStore/Microsoft.NET.Native.Runtime.2.2_2.2.28604.0_x86__8wekyb3d8bbwe.Appx and /dev/null differ diff --git a/Packages/WindowsStore/Microsoft.StorePurchaseApp_12011.1000.2013.0_neutral_~_8wekyb3d8bbwe.appxbundle b/Packages/WindowsStore/Microsoft.StorePurchaseApp_12011.1000.2013.0_neutral_~_8wekyb3d8bbwe.appxbundle deleted file mode 100644 index 76ead39..0000000 Binary files a/Packages/WindowsStore/Microsoft.StorePurchaseApp_12011.1000.2013.0_neutral_~_8wekyb3d8bbwe.appxbundle and /dev/null differ diff --git a/Packages/WindowsStore/Microsoft.StorePurchaseApp_8wekyb3d8bbwe.xml b/Packages/WindowsStore/Microsoft.StorePurchaseApp_8wekyb3d8bbwe.xml deleted file mode 100644 index 8133602..0000000 --- a/Packages/WindowsStore/Microsoft.StorePurchaseApp_8wekyb3d8bbwe.xml +++ /dev/null @@ -1 +0,0 @@ -9NBLGGH4LS1Fmicrosoft.storepurchaseapp_8wekyb3d8bbwea8301a7a-06f7-425e-8fb5-ebfb702440df2c3f1d47-426d-c7d7-face-ef1add208818False2016-04-01T22:02:43.4444915Z2016-04-01T22:02:43.0608594Z2016-04-01T22:02:43.0608594ZFAAAALoAAADJAAAACgAAAAMAAQAD8P5WAgDLAAAAEAAAAAYtUCgpnRSFHl1kRHEW15jOAAAAUgAAAG0AaQBjAHIAbwBzAG8AZgB0AC4AcwB0AG8AcgBlAHAAdQByAGMAaABhAHMAZQBhAHAAcABfADgAdwBlAGsAeQBiADMAZAA4AGIAYgB3AGUAAADNAAAAIgAAAAEAMPDiheq+DxYSDJaaOq7obPBL5IlMNiWK7M2dpI865e8gAAAABAAAAAPw/lbMAAAARAAAAAEAAgCVOMM09off+6NXUn50Ct6Pw0Nc1vQYj/q1lncPdmHi2L06skc87Z+WxfZQmqdsuERDP/S/l3I1ThyK+o9S+73WwnqdrNUltStkbVpNc1Fq5IKTPRvEU6bTBjRLvJ064AE=S0Gc1y9ck1pyaQn0jbLG2eI6Jkw/AjTu9Rpyc1u9qedNB1C5e9jKBLf0B3GTnALSnt87G0dqLZru6kqBLLjXoLUChtxgf4NA8J9MMeQeEWfuFtv1j5rucmvfEsRlU/dKs1q46z7GKzIX0Yl3dAEkbEKAEdUqvdBijjuRDwLckOVz0rBvFZy4qwQ+W2hP0UfgDoHiPdS9vi5VE8odzB0SO/MUxpAT/DuixrWVghqqyU9x+uVMYE9C328mNDTK3bkRiCR/bzl4EsoShTVNxdQrRFnnlB3vaOIUEg5Ge6OkGrYp69M4f82k92rH3OzlQr+qdm2UkKNAMkpI5mrwo2zuGA==oVSJXItDsaAIfwyR9bhh/ZSppCAO+in9POLWdC2/TQodgeHZzbdBvxJvKhpbrq6ZP0FsSElLwRoLAmv7zIuVw3Vb7tfQt5bjCDHRAG9fesNlYKV3ybyNrHyzglfZPRB5UJZw32yi03zQa+LLa05fjs6joEmlHc5BrGQrGrbNMBahz4cmuxKC4/dhEb7JZFUkc0MRhs/M3Ve511HQfKuG+92g1OffJdRsAPzWRdskPoN35knnqno7F85OBmGV/LNBgdtDWUH6di1eUCQFeKGfMp+Q/LFUX9jawTTEPn72tYbpYASug05Skcg6KTHlcLGzevxGw7BYsOsqfDka5n0YGw==AAEAAQ== \ No newline at end of file diff --git a/Packages/WindowsStore/Microsoft.VCLibs.140.00_14.0.27810.0_x64__8wekyb3d8bbwe.Appx b/Packages/WindowsStore/Microsoft.VCLibs.140.00_14.0.27810.0_x64__8wekyb3d8bbwe.Appx deleted file mode 100644 index 7f03af3..0000000 Binary files a/Packages/WindowsStore/Microsoft.VCLibs.140.00_14.0.27810.0_x64__8wekyb3d8bbwe.Appx and /dev/null differ diff --git a/Packages/WindowsStore/Microsoft.VCLibs.140.00_14.0.27810.0_x86__8wekyb3d8bbwe.Appx b/Packages/WindowsStore/Microsoft.VCLibs.140.00_14.0.27810.0_x86__8wekyb3d8bbwe.Appx deleted file mode 100644 index 7e4bddd..0000000 Binary files a/Packages/WindowsStore/Microsoft.VCLibs.140.00_14.0.27810.0_x86__8wekyb3d8bbwe.Appx and /dev/null differ diff --git a/Packages/WindowsStore/Microsoft.WindowsStore_12010.1001.213.0_neutral_~_8wekyb3d8bbwe.appxbundle b/Packages/WindowsStore/Microsoft.WindowsStore_12010.1001.213.0_neutral_~_8wekyb3d8bbwe.appxbundle deleted file mode 100644 index 6c67162..0000000 Binary files a/Packages/WindowsStore/Microsoft.WindowsStore_12010.1001.213.0_neutral_~_8wekyb3d8bbwe.appxbundle and /dev/null differ diff --git a/Packages/WindowsStore/Microsoft.WindowsStore_8wekyb3d8bbwe.xml b/Packages/WindowsStore/Microsoft.WindowsStore_8wekyb3d8bbwe.xml deleted file mode 100644 index 2353283..0000000 --- a/Packages/WindowsStore/Microsoft.WindowsStore_8wekyb3d8bbwe.xml +++ /dev/null @@ -1 +0,0 @@ -9WZDNCRFJBMPmicrosoft.windowsstore_8wekyb3d8bbwe20ae9d1d-4b7d-4c35-b7d6-65e31396efd32c3f1d47-426d-c7d7-face-ef1add208818False2015-06-01T18:28:54.3098854Z2015-06-01T18:28:54.3574657Z2015-06-01T18:28:54.3574657ZFAAAALIAAADJAAAACgAAAAMAAQBmpGxVAgDLAAAAEAAAAPH+T+ZG4jK2WVtWB2o/p3bOAAAASgAAAG0AaQBjAHIAbwBzAG8AZgB0AC4AdwBpAG4AZABvAHcAcwBzAHQAbwByAGUAXwA4AHcAZQBrAHkAYgAzAGQAOABiAGIAdwBlAAAAzQAAACIAAAABAAaf7l9Jp21JeRrJKBhcbP6ODp40LTKLpK3I9WgJHJhOIAAAAAQAAABmpGxVzAAAAEQAAAABAAIAHJNoXjtSbcT3K6z4K6PvH4xijDdLWKmaFiS9nm3Qze7YKZpMaHEm1aiE13HD0bKHyHyl5tAXOn8UgIHHFZ8i6g==RRM/4J8WsRpcxBMBpyvG7aUsW0jEomzv7f++SIVEVDc=ZoYDzCjHhwPTGGBopKxKsXIuvKveOvKlLVFi3inlQUSG/4yJELe1Eu/3e02s2ImCRq/Zxkue+bWXcQG/YdD8MtAQ1Q1BcqqhW3/xQt7cRBX/dwE+SVxvyFr+l7kNkzg8r7UtMMTPHmVsdH5rGR6Ej0kEW8eqUvq9Tbs6MpXFOzwIYrqbwu+LEeWfmL1UZ0DgcGBEGRupgEBzxS362H6R//oReEN0OgSWUhMZcGBuI0rJIOICntxhU/dtsksxGwwoVPheAeCAdDvjZlShWERm0T9aQnOdDqhVY96sH0DTB90GVwXZsvzksXSzdSk4rbjHRinXBS/2HHXu49iy3dXBjg==oVSJXItDsaAIfwyR9bhh/ZSppCAO+in9POLWdC2/TQodgeHZzbdBvxJvKhpbrq6ZP0FsSElLwRoLAmv7zIuVw3Vb7tfQt5bjCDHRAG9fesNlYKV3ybyNrHyzglfZPRB5UJZw32yi03zQa+LLa05fjs6joEmlHc5BrGQrGrbNMBahz4cmuxKC4/dhEb7JZFUkc0MRhs/M3Ve511HQfKuG+92g1OffJdRsAPzWRdskPoN35knnqno7F85OBmGV/LNBgdtDWUH6di1eUCQFeKGfMp+Q/LFUX9jawTTEPn72tYbpYASug05Skcg6KTHlcLGzevxGw7BYsOsqfDka5n0YGw==AAEAAQ== \ No newline at end of file diff --git a/Packages/WindowsStore/Microsoft.XboxIdentityProvider_12.67.21001.0_neutral_~_8wekyb3d8bbwe.appxbundle b/Packages/WindowsStore/Microsoft.XboxIdentityProvider_12.67.21001.0_neutral_~_8wekyb3d8bbwe.appxbundle deleted file mode 100644 index 22383e0..0000000 Binary files a/Packages/WindowsStore/Microsoft.XboxIdentityProvider_12.67.21001.0_neutral_~_8wekyb3d8bbwe.appxbundle and /dev/null differ diff --git a/Packages/WindowsStore/Microsoft.XboxIdentityProvider_8wekyb3d8bbwe.xml b/Packages/WindowsStore/Microsoft.XboxIdentityProvider_8wekyb3d8bbwe.xml deleted file mode 100644 index e4010ac..0000000 --- a/Packages/WindowsStore/Microsoft.XboxIdentityProvider_8wekyb3d8bbwe.xml +++ /dev/null @@ -1 +0,0 @@ -9WZDNCRD1HKWmicrosoft.xboxidentityprovider_8wekyb3d8bbwe15a58266-bcff-4ee0-91f9-315ff813936a2c3f1d47-426d-c7d7-face-ef1add208818False2016-02-20T19:07:41.1189892Z2016-02-20T19:07:40.9422576Z2016-02-20T19:07:40.9422576ZFAAAAMIAAADJAAAACgAAAAMAAQB9uchWAgDLAAAAEAAAABoq1MM/L6mkagTMGyNEhfvOAAAAWgAAAG0AaQBjAHIAbwBzAG8AZgB0AC4AeABiAG8AeABpAGQAZQBuAHQAaQB0AHkAcAByAG8AdgBpAGQAZQByAF8AOAB3AGUAawB5AGIAMwBkADgAYgBiAHcAZQAAAM0AAAAiAAAAAQDwzmDCtA2xOY++tCB7M16iflwLDnYpa1uHDY1XwsgdRyAAAAAEAAAAfbnIVswAAABEAAAAAQACAA1ST4slzJ4Gp3ms6V/TBuTK+mmQyhsquAlbksVmHOGGXfd2JnVaoKWScx8Dn6o88wWwQPqnWF/6QMISZLDXBgE=uvKEEs3RJfIFW/HdJ1h6CAkLr2PLsJGl07/6ndV0mLY=oA1IZpnzE4ocdvFwp3Obf57L9dSe/p/jYINwjGMINETHP2vohVdKsyBHfn9vKWao7nWuI5BYZJR1pfSlCtVQuJxavzaE+cCKtokJG+UYcRz/cJ8BBzi9sG2z62QrAbXGdFArvvaVM77s7DAjXgeGP4HWjSSM64k1aHGfKzfwexSgAyKetEto7nTrLleKtKWKxfx3CKLLRpbVBU+D//m+dXFuxIe+OCIMepFBr4udAYeAJYyFxgPKqHeqGrM8IAWoXHtZmoiKLFndDTpUsBNlvZLbyouw9W7rGYzkSE3htXIhExJilbTXXe+L5v4YD5w+1AalGAIJR42M9RZyYOGWLw==oVSJXItDsaAIfwyR9bhh/ZSppCAO+in9POLWdC2/TQodgeHZzbdBvxJvKhpbrq6ZP0FsSElLwRoLAmv7zIuVw3Vb7tfQt5bjCDHRAG9fesNlYKV3ybyNrHyzglfZPRB5UJZw32yi03zQa+LLa05fjs6joEmlHc5BrGQrGrbNMBahz4cmuxKC4/dhEb7JZFUkc0MRhs/M3Ve511HQfKuG+92g1OffJdRsAPzWRdskPoN35knnqno7F85OBmGV/LNBgdtDWUH6di1eUCQFeKGfMp+Q/LFUX9jawTTEPn72tYbpYASug05Skcg6KTHlcLGzevxGw7BYsOsqfDka5n0YGw==AAEAAQ== \ No newline at end of file diff --git a/Packages/WindowsStore/placeholder.txt b/Packages/WindowsStore/placeholder.txt new file mode 100644 index 0000000..67c3297 --- /dev/null +++ b/Packages/WindowsStore/placeholder.txt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/README.md b/README.md index 70ce7fe..050a72b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Optimize-Offline # -Optimize-Offline is a Windows Image (WIM/ESD) optimization module designed for Windows 10 versions 1803-to-2004 64-bit architectures. +Optimize-Offline is a Windows Image (WIM/ESD) optimization module designed for Windows 10 versions 1803-to-2009 64-bit architectures. ## About Optimize-Offline ## @@ -61,6 +61,8 @@ The following System Applications are safe to remove: Cortana can also be removed, though doing so will render the default search feature inoperable and is only recommended if a 3rd party search program like Classic Shell will be used. +AppResolverUX is a UWP app that not only issues the pop-up asking how to open a specific file that does not have its own dedicated app association, but also allows for the installation of DHC drivers. It is advised not to remove this System Application as doing so will prevent all Store, UWP/DHC driver apps from running and also prevent them from being manually installed. + **Some System Applications are required during the OOBE setup pass and their removal can cause setup to fail. Do not remove any System Application if you're unsure of its impact on a live system.** ### About Windows Capabilities and Packages ### @@ -134,6 +136,33 @@ It is also recommended to be well versed and aware of all recovery tools Microso Starting in Windows 8.1, Microsoft introduced a Metro-style calculator to replace its traditional Calculator. In Windows 10 non-LTSB/LTSC/Server editions, the traditional Calculator was entirely removed and replaced with a UWP (Universal Windows Platform) App version. This new UWP Calculator introduced a fairly bloated UI many users were simply not fond of and much preferred the simplicity of the traditional Calculator (now labeled Win32Calc.exe). Unfortunately, Microsoft never added the ability to revert back to the traditional Calculator nor released a downloadable package to install the traditional Calculator. +### About Microsoft Defender + +> Microsoft Defender is the built-in antimalware and antivirus protection component of Microsoft Windows. [Microsoft Document](https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/microsoft-defender-antivirus-windows?view=o365-worldwide). Natively, unless replaced by another antivirus, the Defender application always starts with Windows. Optimize-Offline provides methods to regain control over the initial activation and ongoing operation of Microsoft Defender. + +***Optimize-Offline supplies two methods to control Microsoft Defender*** + +- The first method is to remove the SecHealthUI package which totally and permanently disables Defender. +- The second method is to apply the Dormant Defender parameter which provides greater flexibility in controlling Microsoft Defender. + +***Option #1 - remove the SecHealthUI package and permanently disable Defender*** + +- For Windows 10: Remove SecHealthUI from System Applications. See [GitHub-DrEmpiricism](https://github.com/DrEmpiricism/Optimize-Offline#about-system-applications) +- For Windows 11: SecHealthUI removal is handled by your chosen WindowsApps list. See [GitHub-gdeliana](https://github.com/gdeliana/Optimize-Offline/blob/master/README.md#using-component-removal-lists) + +***Option #2 - Apply the Dormant Defender parameter to gain full control of Defender*** + +For all Windows builds. The Dormant Defender parameter applies entries and values to the image registry hives forcing Microsoft Defender into an inactive state. +Dormant Defender fully disables Microsoft Defender, but by leaving the application and folder structure intact, retains the possibility to restore it to full functionality. + +To re-enable Defender apply the "Microsoft Defender Enable" script [GitHub-TairikuOokami](https://github.com/TairikuOokami/Windows/blob/main/Microsoft%20Defender%20Enable.bat). + +After Microsoft Defender is restored, retain full control by applying the "ToggleDefender" script [GitHub-AveYo](https://github.com/AveYo/LeanAndMean#toggledefender---lean-and-mean-snippet-by-aveyo-2020-2021). + +***Note:*** + +If you apply both methods to control Microsoft Defender e.g. remove the SecHealthUI package and apply the Dormant Defender parameter, then the former removal method takes precedence. Meaning that the outcome of applying both methods is the same as if you only removed the SecHealthUI package. + ### About Data Deduplication ### > Data Deduplication, often called Dedup for short, is a feature of Windows Server 2016 that can help reduce the impact of redundant data on storage costs. When enabled, Data Deduplication optimizes free space on a volume by examining the data on the volume by looking for duplicated portions on the volume. Duplicated portions of the volume's dataset are stored once and are (optionally) compressed for additional savings. Data Deduplication optimizes redundancies without compromising data fidelity or integrity. [Microsoft Document](https://docs.microsoft.com/en-us/windows-server/storage/data-deduplication/overview) @@ -195,3 +224,148 @@ Once you have edited the Configuration.json to your specific optimization requir ```PowerShell .\Start-Optimize.ps1 ``` + +## Using Optimize-Offline as TrustedInstaller + +Running Optimize-Offline as Trusted Installer enhances every operation it performs including properly unloading the image. This enhanced capability is provided by the "Start-Optimize-BAU-TI.ps1" script. The script is a the custom-made version of the generic "RunAsTI" script [GitHub-AveYo](https://github.com/AveYo/LeanAndMean/blob/main/RunAsTI.bat) and includes a unique solution for providing the power of Trusted Installer, but still correctly loading the HKCU USER hive as opposed to Window's natively loading the TI SYSTEM hive. + +Open the custom configuration JSON file (Configuration.json) in any text editing program and edit any values for your specific optimization requirements. While editing the Configuration.json file, do not change the template structure and make sure its formatting is retained when adding or changing values. + +Once you have edited the Configuration.json to your specific optimization requirements, open an elevated PowerShell console in the root directory of the Optimize-Offline project and execute the Start-Optimize-BAU-TI call script: + +```PowerShell +.\Start-Optimize-BAU-TI.ps1 +``` + +## Using Optimize-Offline GUI + +For now there exists also a simple GUI variant that just prepares configuration.json file and is able to launch the script. + +To use the GUI version of the script, please run/double click: + +``` +.\Start-GUI.bat +``` + +Below you will find a detailed explanation of each of the GUI sections: + +* Source select button - Opens a file picker dialog. Choose the source of the modification process. +* Output select button - Opens a file save dialog, where the modified output will be saved. By default the output is saved in a automatically created subfolder of the root directory of the script. +* Refresh lists button - Will obtain all the available items for removal from the selected media. This automatically happens whenver a source file is chosen. +* Process button - Launches the Optimize-Offline script and switches to the output tab, to view the console output of the script. +* Select USB - Select the USB where to flash the modified target file +* UEFI/LEGACY - Select the type of USB to create. Use legacy for older bioses. +* General tab - contains general options that can be found in the configuration.json. By hovering the mouse on each of the options you will get a brief description of what the option does. +* Windows Apps - Select the Windows apps to remove/protect from removal. Blacklist will remove the selected apps, whereas whitelist will remove the not selected. +* System Apps - Select the System inbox apps to remove (some of them may render the installation unbootable). Blacklist will remove the selected system apps, whereas whitelist will remove the not selected. +* Capabilities - Removes windows capabilities. Blacklist will remove the selected capabilities, whereas whitelist will remove the not selected. +* Packages - Removes windows packages. Blacklist will remove the selected packages, whereas whitelist will remove the not selected. +* Features - Sets the windows feature to enable or disable. +* Services - Sets the startup of the windows services. BE CAREFUL!! not all the items listed are windows services. Due to the registry key containing also items such driver services that are not normal windows services. +* Custom registry - Injects registry tweaks into the installation +* Output - Shows an embeded console of the Optimize-Offline script output. + +## Using component removal lists + +Removal lists can be found in ./Content/Lists. There are 6 basic categories spread out through each of the subfolders. In each subcategory you will find a Whitelist, Blacklist and a template. The template contains all the possible packages to be inserted either in the blacklist or in the whitelist. The features contain only a list json and a template. + +- WindowsApps - WindowsAppsWhitelist.json, WindowsAppsBlacklist.json, WindowsAppsTemplate.json +- SystemApps - SystemAppsWhitelist.json, SystemAppsBlacklist.json, SystemAppsTemplate.json +- Capabilities - CapabilitiesWhitelist.json, CapabilitiesBlacklist.json, CapabilitiesTemplate.json +- Packages - PackagesWhitelist.json, PackagesBlacklist.json, PackagesTemplate.json +- FeaturesToEnable - FeaturesToEnableList.json, FeaturesToEnableTemplate.json +- FeaturesToDisable - FeaturesToDisableList.json, FeaturesToDisableTemplate.json + +The template files can be filled by launching the script with the populateTemplates parameter + +```PowerShell +.\Start-Optimize.ps1 -populateTemplates +``` + +In configuration.json the list parameters are the following: + +- WindowsApps - (All, None, Select, Whitelist, Blacklist), lists are in ./Content/Lists/WindowsApps +- SystemApps - (All, None, Select, Whitelist, Blacklist), lists are in ./Content/Lists/SystemApps +- Capabilities - (All, None, Select, Whitelist, Blacklist), lists are in ./Content/Lists/Capabilities +- Packages - (All, None, Select, Whitelist, Blacklist), lists are in ./Content/Lists/Packages +- FeaturesToEnable - (All, None, Select, List), lists are in ./Content/Lists/FeaturesToEnable +- FeaturesToDisable - (All, None, Select, List), lists are in ./Content/Lists/FeaturesToDisable +- Services - (None, Select, List, Advanced), lists are in ./Content/Lists/ServicesList.json, and in ./Content/Lists/ServicesAdvanced.json when advanced parameter is set in configuration.json + +## Generating template component removal lists + +The component removal lists mentioned above contain package names that are found in the windows system. Each version of windows may change the names and entries of it's components. For updating the lists or even helping you in generating custom ones according to the windows build you have, use the command: + +`.\Start-Optimize -populateTemplates` + +This command will find all the available windows apps, system apps and capabilities and will fill the corresponding json located in ./Content/Lists . Afterwards feel free to cherry pick the package names and insert them according to your needs in the removal lists in subfolder ./Content/Lists. + +To populate the lists interactively by clicking item in grid guis and as well populating the templates (for later making manual changes to the lists by copying and pasting), use this command: +Code: + +`.\Start-Optimize.ps1 -populateLists` + +Please note that the interactive filling of lists, will fill the list chosen in configuration.json. So first set up configuration.json with the proper list method!! If no list methods are specified in configuration.json the populateLists will just populate the templates, as it doesn't have info about which lists to fill, so it will be basically the same behaviour like populateTemplates. + +## Flashing to USB + +In order to flash to an USB device, please set the key FlashToUSB to "UEFI" or "Legacy" value. +The Legacy option uses `\boot\bootsect.exe /nt60` method. +The UEFI method creates a special UEFI partition in the USB drive and then sets it as bootable. +Depending on your bios capabilities and on the boot method, choose the right method for your PC. + +## Custom Icons + +You can customize the icons of the windows local disk volume and of the ISO/USB volumes. +To set a custom windows local disk icon place it under `Content\Assets\windows.ico` +To set a custom USB drive/ISO disk icon place it under `Content\Assets\setup.ico` + +## Windows services removal + +***==Services Template==*** +Use populateTemplates feature to assign your images available services to ServicesTemplate.json + Some filtering out of non-service related entries is complete in the provided ServicesTemplate.json, but each OS requires more filtering. + +***==List==*** +Set the Services parameter in configuration.json: List +Assigns the start behavior of the services listed in ServicesList.json to "Disabled" + For Services you want to disable, copy the service object "name" . . . + . . . from /Content/Lists/Services/ServicesTemplate.json -> /Content/Lists/Services/ServicesList.json + Alternatively, if you already have a list of services you know you want to disable, add their names following the pattern seen in the provided example ServicesList.json + +***==Advanced==*** +Set the Services parameter in configuration.json: Advanced +Useful for specifying any type of start behavior (including "4" "Disabled") to the services listed in ServicesAdvanced.json + Specify the start behavior of each service by copying the object . . . + Code: + { + name: [SERVICE_DISPLAYNAME], + start: [0,1,2,3,4], + description?: [optional, not used in the code, but just for you to know more about the services you're including] + } + . . . from /Content/Lists/Services/ServicesTemplate.json -> /Content/Lists/Services/ServicesAdvanced.json + +## Selecting the output path and filename + +You can override the default path for ISO/WIM/SWM/ESD files by entering a specific path with an optional filename in Configuration.json "OutputPath" key. The possible key values are the following: + +- default - is the default value for this setting and represents the default behavior of the script +- select - will popup a save file dialog for ISO input and a choose directory dialog for WIM/SWM/ESD inputs +- your specific path - you can as well specify the exact path of the output. For WIM/SWM/ESD files the path will chose only the directory path and any filename will be ignored. +- your specific path with {filename} variable for ISO inputs - The name of the ISO can be left to the script to be specified automatically based on the filename convention: {Windows_Edition}_{Build_nr}.ISO (ex. Professional_22000.ISO) + +## Selective registry tweaks + +- DisableWindowsUpgrade - Tweak will prevent windows update from receiving cummulative updates and feature updates +- DisableWindowsUpdateMicrosoft - Applies the official developers solution to prevents Windows Update from connecting to Microsoft update services. This includes connecting to the MS Store to download apps. [Microsoft Document] (https://docs.microsoft.com/en-us/windows/privacy/manage-connections-from-windows-operating-system-components-to-microsoft-services#bkmk-wu) Easy to turn on an off using a toggle script [GitHub Gist] (https://gist.github.com/espanafly/3041ce74cd2493d349e58c31630f98e5) +- DisableDriverUpdate - Will disable windows update from updating hw drivers +- DormantOneDrive - Disables the startup installation of Onedrive, but allows you to manually install by using the dormant physical setup file +- Disable3rdPartyApps - Will remove the 3rd party apps installed with windows +- W11ClassicContextMenu - Will make the context menu look like in W10 (builds >= 22000) +- ExplorerUIRibbon - Enables the classic explorer UI ribbon (not available on builds >= 22500) +- ClassicSearchExplorer - Tweak is needed in case you uninstall Search app or when applying the /Content/Additional/Setup/Set-Additional.ps1 on an online image. Works only on builds higher than 18363. +- RemoveTaskbarPinnedIcons - Tries to remove based on system version the automatically pinned taskbar icons +- DisableTeamsApp - Will remove Microsoft Teams from installing at the first logon +- DisableVirtualizationSecurity - Disables Core integrity and Virtualization based security (builds >= 22000) +- RunAsTiContextMenu - Adds Powershell as trusted installer context menu entry +- AmoledBlackTheme - Enables pitch black AMOLED theme on W10 and W11 all builds diff --git a/Remove_Failure_no_prompts.cmd b/Remove_Failure_no_prompts.cmd new file mode 100644 index 0000000..6804f92 --- /dev/null +++ b/Remove_Failure_no_prompts.cmd @@ -0,0 +1,72 @@ +@setlocal DisableDelayedExpansion +@echo off +set _args= +set _args=%* +if not defined _args goto :NoProgArgs +for %%A in (%_args%) do ( +if /i "%%A"=="-wow" set _rel1=1 +if /i "%%A"=="-arm" set _rel2=1 +) +:NoProgArgs +set "_cmdf=%~f0" +if exist "%SystemRoot%\Sysnative\cmd.exe" if not defined _rel1 ( +setlocal EnableDelayedExpansion +start %SystemRoot%\Sysnative\cmd.exe /c ""!_cmdf!" -wow " +exit /b +) +if exist "%SystemRoot%\SysArm32\cmd.exe" if /i %PROCESSOR_ARCHITECTURE%==AMD64 if not defined _rel2 ( +setlocal EnableDelayedExpansion +start %SystemRoot%\SysArm32\cmd.exe /c ""!_cmdf!" -arm " +exit /b +) +set "_Null=1>nul 2>nul" +set "SysPath=%SystemRoot%\System32" +if exist "%SystemRoot%\Sysnative\reg.exe" (set "SysPath=%SystemRoot%\Sysnative") +set "Path=%SysPath%;%SystemRoot%;%SysPath%\Wbem;%SysPath%\WindowsPowerShell\v1.0\" +reg.exe query HKU\S-1-5-19 %_Null% || (echo.&echo This script require administrator privileges.&goto :TheEnd) +set _drv=%~d0 +set "xOS=%PROCESSOR_ARCHITECTURE%" +if /i %PROCESSOR_ARCHITECTURE%==x86 (if defined PROCESSOR_ARCHITEW6432 set "xOS=%PROCESSOR_ARCHITEW6432%") +set "_key=HKLM\SOFTWARE\Microsoft\WIMMount\Mounted Images" +set regKeyPathFound=1 +set wowRegKeyPathFound=1 +reg.exe query "HKLM\Software\Wow6432Node\Microsoft\Windows Kits\Installed Roots" /v KitsRoot10 %_Null% || set wowRegKeyPathFound=0 +reg.exe query "HKLM\Software\Microsoft\Windows Kits\Installed Roots" /v KitsRoot10 %_Null% || set regKeyPathFound=0 +if %wowRegKeyPathFound% equ 0 ( + if %regKeyPathFound% equ 0 ( + goto :precheck + ) else ( + set regKeyPath=HKLM\Software\Microsoft\Windows Kits\Installed Roots + ) +) else ( + set regKeyPath=HKLM\Software\Wow6432Node\Microsoft\Windows Kits\Installed Roots +) +for /f "skip=2 tokens=2*" %%i in ('reg.exe query "%regKeyPath%" /v KitsRoot10') do set "KitsRoot=%%j" +set "DandIRoot=%KitsRoot%Assessment and Deployment Kit\Deployment Tools" +if exist "%DandIRoot%\%xOS%\DISM\dism.exe" ( +set "Path=%DandIRoot%\%xOS%\DISM;%SysPath%;%SystemRoot%;%SysPath%\Wbem;%SysPath%\WindowsPowerShell\v1.0\" +cd \ +) + +:precheck +@cls +for /f "tokens=3*" %%a in ('reg.exe query "%_key%" /s /v "Mount Path" 2^>nul ^| findstr /i /c:"Mount Path"') do (set "_mount=%%b"&call :CLN) +dism.exe /English /Cleanup-Wim +dism.exe /English /Cleanup-Mountpoints +goto :TheEnd + +:CLN +dism.exe /English /Image:"%_mount%" /Get-Packages %_Null% +dism.exe /English /Unmount-Wim /MountDir:"%_mount%" /Discard +if exist "%_mount%\" rmdir /s /q "%_mount%\" %_Null% +if exist "%_mount%" ( +mkdir %_drv%\_del286 %_Null% +robocopy %_drv%\_del286 "%_mount%" /MIR /R:1 /W:1 /NFL /NDL /NP /NJH /NJS %_Null% +rmdir /s /q %_drv%\_del286\ %_Null% +rmdir /s /q "%_mount%" %_Null% +) +exit /b + +:TheEnd +echo. +goto :eof diff --git a/Src/GUI/Configuration_definition.json b/Src/GUI/Configuration_definition.json new file mode 100644 index 0000000..6c0e408 --- /dev/null +++ b/Src/GUI/Configuration_definition.json @@ -0,0 +1,289 @@ +{ + "Main": { + "Label": "Main", + "Column": 1, + "Controls": [ + { + "Name": "DormantDefender", + "Label": "Disable Windows Defender/Security", + "Type": "Switch", + "Binding": "DormantDefender", + "Description": "Disable Windows defender while retaining the option to reactivate it." + }, + { + "Name": "Registry", + "Label": "Apply Registry tweaks", + "Type": "Switch", + "Binding": "Registry", + "Description": "For the specifics check file: .\\Src\\Public\\Set-RegistryProperties.ps1" + }, + { + "Name": "ComponentCleanup", + "Label": "Clean the Component Store", + "Type": "Switch", + "Binding": "ComponentCleanup", + "Description": "compresses all superseded components, thus reducing the size of the Component Store" + }, + { + "Name": "Win32Calc", + "Label": "Integrate classic windows calculator", + "Type": "Switch", + "Binding": "Win32Calc", + "Description": "Integrates the traditional Win32 Calculator into the image." + }, + { + "Name": "DeveloperMode", + "Label": "Developer mode", + "Type": "Switch", + "Binding": "DeveloperMode", + "Description": "Enables developer mode" + }, + { + "Name": "WindowsStore", + "Label": "Integrate Windows Store", + "Type": "Switch", + "Binding": "WindowsStore", + "Description": "Integrate Windows Store" + }, + { + "Name": "Dedup", + "Label": "Integrate Windows Server Data Deduplication", + "Type": "Switch", + "Binding": "Dedup", + "Description": "Integrates the Windows Server Data Deduplication Feature into the image." + }, + { + "Name": "MicrosoftEdge", + "Label": "Integrate Microsoft Edge Chromium", + "Type": "Switch", + "Binding": "MicrosoftEdge", + "Description": "Only works on windows 10 builds without Edge Chromium", + "Restrictions": [ + { + "Build": "18362", + "Criteria": "min" + }, + { + "Build": "19041", + "Criteria": "max" + } + ] + }, + { + "Name": "ISO", + "Label": "Prompt at boot", + "Type": "ComboBox", + "Description": "Prompt at boot", + "Values": ["Prompt", "No-Prompt"], + "Binding": "ISO", + "ShowNone": false + }, + { + "Name": "CompressionType", + "Label": "WIM/ESD compression level", + "Type": "ComboBox", + "Description": "WIM/ESD compression level", + "Values": ["None", "Fast", "Maximum", "Solid"], + "Binding": "CompressionType", + "ShowNone": false + }, + { + "Name": "ShutDownOnComplete", + "Label": "Turn off pc on script completion", + "Type": "Switch", + "Binding": "ShutDownOnComplete", + "Description": "Turn off pc on script completion, when clicking the process button" + } + ] + }, + "Additional": { + "Label": "Additional", + "Column": 0, + "Controls": [ + { + "Name": "Setup", + "Label": "Apply Setup Content", + "Type": "Switch", + "Binding": "Additional.Setup", + "Description": "Integrates user-specific content added to the 'Content/Additional' directory into the image when enabled" + }, + { + "Name": "Wallpaper", + "Label": "Apply Wallpaper", + "Type": "Switch", + "Binding": "Additional.Wallpaper", + "Description": "Integrates 'Content\\Additional\\Wallpaper\\Windows 10 HD' wallpapers in the image" + }, + { + "Name": "SystemLogo", + "Label": "Apply System Logo", + "Type": "Switch", + "Binding": "Additional.SystemLogo", + "Description": "Integrates a custom system logo into the image. Place the logo in 'Content\\Additional\\SystemLogo'" + }, + { + "Name": "LockScreen", + "Label": "Apply LockScreen", + "Type": "Switch", + "Binding": "Additional.LockScreen", + "Description": "Converts and integrates a custom lockscreen into the image. Place the lockscreen files into 'Content\\Additional\\LockScreen'" + }, + { + "Name": "RegistryTemplates", + "Label": "Apply Additional Registry", + "Type": "Switch", + "Binding": "Additional.RegistryTemplates", + "Description": "Custom registry template (.reg) files placed in the '\\Content\\Additional\\RegistryTemplates' folder are imported by Optimize-Offline into the offline image's appropriate registry hive." + }, + { + "Name": "LayoutModification", + "Label": "Apply custom Start Menu layout", + "Type": "Switch", + "Binding": "Additional.LayoutModification", + "Description": "Imports a custom LayoutModification.xml to provision the Start layout.If adding additional user content, place any custom Start Menu layout XML/JSON (LayoutModification.xml/LayoutModification.json) file to be added to the image in '\\Content\\Additional\\LayoutModification'" + }, + { + "Name": "Unattend", + "Label": "Apply answer file", + "Type": "Switch", + "Binding": "Additional.Unattend", + "Description": "Place the answer file (unattend.xml) into '\\Content\\Additional\\Unattend' folder" + }, + { + "Name": "Drivers", + "Label": "Integrate Windows drivers", + "Type": "Switch", + "Binding": "Additional.Drivers", + "Description": "Place the drivers into '\\Content\\Additional\\Drivers' folder" + }, + { + "Name": "NetFx3", + "Label": "Integrate .Net Framework 3.5", + "Type": "Switch", + "Binding": "Additional.NetFx3", + "Description": "Integrates the .NET Framework 3 payload packages into the image and enables the NetFx3 optional feature. Works only when input is an ISO image." + } + ] + }, + "SelectiveRegistry": { + "Label": "Selective registry", + "Column": 0, + "Controls": [ + { + "Name": "DisableWindowsUpgrade", + "Label": "Disable Windows upgrade", + "Type": "Switch", + "Binding": "SelectiveRegistry.DisableWindowsUpgrade", + "Description": "Disables the ability to upgrade to newer versions of Windows" + }, + { + "Name": "DisableWindowsUpdateMicrosoft", + "Label": "Disabling Windows update contacting Microsoft servers", + "Type": "Switch", + "Binding": "SelectiveRegistry.DisableWindowsUpdateMicrosoft", + "Description": "This disables completely the windows update services and Microsoft Store downloading" + }, + { + "Name": "DisableDriverUpdate", + "Label": "Disable Windows driver update", + "Type": "Switch", + "Binding": "SelectiveRegistry.DisableDriverUpdate", + "Description": "Disabled Windows update from automatically updating drivers" + }, + { + "Name": "DormantOneDrive", + "Label": "Disable Microsoft OneDrive", + "Type": "Switch", + "Binding": "SelectiveRegistry.DormantOneDrive", + "Description": "Disables Onedrive installation after OOBE run" + }, + { + "Name": "Disable3rdPartyApps", + "Label": "Disable 3rd party app installation", + "Type": "Switch", + "Binding": "SelectiveRegistry.Disable3rdPartyApps", + "Description": "Disables ContentDeliveryManager from installing 3rd party apps. This tweak is activated also in case the system app 'ContentDeliveryManager' is removed from the system apps tab." + }, + { + "Name": "ExplorerUIRibbon", + "Label": "Classic Explorer UI ribbon", + "Type": "Switch", + "Binding": "SelectiveRegistry.ExplorerUIRibbon", + "Description": "Add the explorer UI ribbon in Windows 10" + }, + { + "Name": "ClassicSearchExplorer", + "Label": "Explorer classic file search", + "Type": "Switch", + "Binding": "SelectiveRegistry.ClassicSearchExplorer", + "Description": "Disables modern UWP explorer file search" + }, + { + "Name": "RemoveTaskbarPinnedIcons", + "Label": "Remove taskbar pinned icons", + "Type": "Switch", + "Binding": "SelectiveRegistry.RemoveTaskbarPinnedIcons", + "Description": "Removes taskbar pinned icons" + }, + { + "Name": "DisableTeamsApp", + "Label": "Remove Microsoft Teams App", + "Type": "Switch", + "Binding": "SelectiveRegistry.DisableTeamsApp", + "Description": "Removes Microsoft Teams App" + }, + { + "Name": "RunAsTiContextMenu", + "Label": "Add Run As Trusted Installer context menu entry", + "Type": "Switch", + "Binding": "SelectiveRegistry.RunAsTiContextMenu", + "Description": "Add Run As Trusted Installer context menu entry" + } + ] + }, + "Specific": { + "Label": "Specific", + "Column": 1, + "Controls": [ + { + "Name": "W11ClassicContextMenu", + "Label": "W11 Classic context menus", + "Type": "Switch", + "Binding": "SelectiveRegistry.W11ClassicContextMenu", + "Description": "Makes context menus classic looking, as in W10", + "Restrictions": [ + { + "Build": "22000", + "Criteria": "min" + } + ] + }, + { + "Name": "DisableVirtualizationSecurity", + "Label": "W11 Disable Virtualization Security", + "Type": "Switch", + "Binding": "SelectiveRegistry.DisableVirtualizationSecurity", + "Description": "Disables Core integrity and Virtualization based security (builds >= 22000)", + "Restrictions": [ + { + "Build": "22000", + "Criteria": "min" + } + ] + }, + { + "Name": "AmoledBlackTheme", + "Label": "W11 Add AMOLED Black Theme", + "Type": "Switch", + "Binding": "SelectiveRegistry.AmoledBlackTheme", + "Description": "W11 Add AMOLED Black Theme", + "Restrictions": [ + { + "Build": "22000", + "Criteria": "min" + } + ] + } + ] + } +} diff --git a/Src/GUI/RemovalTemplates/CapabilitiesTemplate.json b/Src/GUI/RemovalTemplates/CapabilitiesTemplate.json new file mode 100644 index 0000000..5051d94 --- /dev/null +++ b/Src/GUI/RemovalTemplates/CapabilitiesTemplate.json @@ -0,0 +1,3 @@ +[ + +] diff --git a/Src/GUI/RemovalTemplates/FeaturesTemplate.json b/Src/GUI/RemovalTemplates/FeaturesTemplate.json new file mode 100644 index 0000000..5051d94 --- /dev/null +++ b/Src/GUI/RemovalTemplates/FeaturesTemplate.json @@ -0,0 +1,3 @@ +[ + +] diff --git a/Src/GUI/RemovalTemplates/PackagesTemplate.json b/Src/GUI/RemovalTemplates/PackagesTemplate.json new file mode 100644 index 0000000..9fc873f --- /dev/null +++ b/Src/GUI/RemovalTemplates/PackagesTemplate.json @@ -0,0 +1,3 @@ +[ + +] diff --git a/Src/GUI/RemovalTemplates/ServicesTemplate.json b/Src/GUI/RemovalTemplates/ServicesTemplate.json new file mode 100644 index 0000000..c9c513b --- /dev/null +++ b/Src/GUI/RemovalTemplates/ServicesTemplate.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/Src/GUI/RemovalTemplates/SystemAppsTemplate.json b/Src/GUI/RemovalTemplates/SystemAppsTemplate.json new file mode 100644 index 0000000..df9e79a --- /dev/null +++ b/Src/GUI/RemovalTemplates/SystemAppsTemplate.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/Src/GUI/RemovalTemplates/WindowsAppsTemplate.json b/Src/GUI/RemovalTemplates/WindowsAppsTemplate.json new file mode 100644 index 0000000..df9e79a --- /dev/null +++ b/Src/GUI/RemovalTemplates/WindowsAppsTemplate.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/Src/GUI/Start.ps1 b/Src/GUI/Start.ps1 new file mode 100644 index 0000000..44cad9b --- /dev/null +++ b/Src/GUI/Start.ps1 @@ -0,0 +1,781 @@ +Add-Type -AssemblyName PresentationFramework, System.Windows.Forms + +$Global:Error.Clear() + +$RootPath = $PSScriptRoot + +$OO_Root_Path = (Get-Item -Path "$RootPath\..\..\").FullName +$OO_Lists_Path = "$($OO_Root_Path)Content\Lists\" +$ConsoleSTDOutPath = "$($OO_Root_Path)ConsoleOut.txt" +$CustomRegistryPath = "$($OO_Root_Path)\Content\CustomRegistry.reg" + +$RemovalTypes = @("Blacklist", "Whitelist") +$ListTypes = @("WindowsApps", "SystemApps", "Capabilities", "Packages", "Services", "Features") +$ListTypesNoRemoval = @("Services", "Features") +$ListColumns = @{ + "WindowsApps" = @("DisplayName", "PackageName") + "SystemApps" = @("DisplayName") + "Capabilities" = @("Name") + "Packages" = @("PackageName") + "Services" = @("Name", "Description") + "Features" = @("FeatureName", "OriginalState") +} +$ListMainKey = @{ + "WindowsApps" = "DisplayName" + "SystemApps" = "DisplayName" + "Capabilities" = "Name" + "Packages" = "PackageName" + "Services" = "Services" + "Features" = "FeatureName" +} +$ListColumnsComboBox = @{ + "Features" = @("State") + "Services" = @("Start") +} + +Function CleanVars { + Remove-Variable -Name Configuration, ConfigurationDef -ErrorAction Ignore + Remove-Variable -Name OO_GUI_FlashUSBDriveNumber, OO_GUI_Timer, OO_GUI_Job -ErrorAction Ignore -Scope Global + Foreach($ListType in $ListTypes) { + Remove-Variable -Name "$($ListType)Template" -ErrorAction Ignore -Scope Global + } + If (Test-Path -Path "$ConsoleSTDOutPath") { + Remove-Item -Path "$ConsoleSTDOutPath" + } +} + +CleanVars + +$Global:OO_GUI_FlashUSBDriveNumber = -1 + +$Global:OO_GUI_Timer = New-Object System.Windows.Forms.Timer +$Global:OO_GUI_Timer.Interval = 3000 + +$Global:OO_GUI_Job = $null + + +$Configuration_path = (Get-Item -Path "$($OO_Root_Path)Configuration.json").FullName + +## Import XAML files +Get-ChildItem -Path "$RootPath\XAML" -Filter *.xaml -Recurse | ForEach-Object -Process { + New-Variable -Name "$($_.BaseName)XAML" -Value (Get-Content -Raw -Path $_.FullName) -Scope Script +} + +## Import the List templates +Function Import-Templates { + Foreach($ListType in $ListTypes){ + If(Test-Path -Path "$RootPath\RemovalTemplates\$($ListType)Template.json") { + $JSON = Get-Content -Raw -Path "$RootPath\RemovalTemplates\$($ListType)Template.json" -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop + } Else { + $JSON = @() + } + If(!$JSON){ + $JSON = @() + } + ## Sync GUI list data from OO list data + Switch($ListType) { + "Services"{ + $Key = $ListMainKey.$ListType + $List_OO = $(Get-Content -Raw -Path "$OO_Lists_Path\Services\ServicesList.json" -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop).$Key + If($List_OO){ + Foreach($Item in $JSON) { + Foreach($ItemOO in $List_OO) { + If ($Item.Name -eq $ItemOO -or ($ItemOO -Match "\*" -and $Item.Name -like $ItemOO)){ + $Item.Start = $Item.Starts[4] + Break + } + } + } + } + $List_OO = $(Get-Content -Raw -Path "$OO_Lists_Path\Services\ServicesAdvanced.json" -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop).$Key + If($List_OO){ + Foreach($Item in $JSON) { + Foreach($ItemOO in $List_OO) { + If($Item.Name -eq $ItemOO.name) { + $Item.Start = $Item.Starts[$ItemOO.start] + Break + } + } + } + } + } + "Features" { + $Key = $ListMainKey.$ListType + $List_OO_ToDisable = $(Get-Content -Raw -Path "$OO_Lists_Path\FeaturesToDisable\FeaturesToDisableList.json" -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop).$Key + $List_OO_ToEnable = $(Get-Content -Raw -Path "$OO_Lists_Path\FeaturesToEnable\FeaturesToEnableList.json" -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop).$Key + If($List_OO_ToDisable){ + Foreach($Item in $JSON) { + Foreach($ItemOO in $List_OO_ToDisable){ + If ($Item.$Key -eq $ItemOO -or ($ItemOO -Match "\*" -and $Item.$Key -like $ItemOO)){ + $Item.State = "Disabled" + } + } + } + } + If($List_OO_ToEnable){ + Foreach($Item in $JSON) { + Foreach($ItemOO in $List_OO_ToEnable){ + If ($Item.$Key -eq $ItemOO -or ($ItemOO -Match "\*" -and $Item.$Key -like $ItemOO)){ + $Item.State = "Enabled" + } + } + } + } + } + default { + If ($Configuration.$ListType){ + $Type = $($Configuration.$ListType).Trim() + $Type = $Type.substring(0,1).toupper()+$Type.substring(1).tolower() + If ($RemovalTypes.IndexOf($Type) -gt -1){ + $Key = $ListMainKey.$ListType + $List_OO = (Get-Content -Raw -Path "$OO_Lists_Path\$($ListType)\$($ListType)List.json" -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop).$Key + If($List_OO){ + Foreach($Item in $JSON) { + Foreach($ItemOO in $List_OO){ + If ($Item.$Key -eq $ItemOO -or ($ItemOO -Match "\*" -and $Item.$Key -like $ItemOO)){ + $Item.Selected = $true + } + } + } + } + } + } + } + } + Remove-Variable -Name "$($ListType)Template" -Scope Global -ErrorAction Ignore + New-Variable -Name "$($ListType)Template" -Value $JSON -Scope Global + } +} + +Import-Templates + +$ConfigurationDef = Get-Content -Path "$RootPath\Configuration_definition.json" -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop +$Configuration = Get-Content -Path $Configuration_path -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop + +Function Save-List { + param([string]$ListType) + $PathList = "$($OO_Lists_Path)$($ListType)\$($ListType)List.json" + $PathTemplate = "$RootPath\RemovalTemplates\$($ListType)Template.json" + $Template = (Get-Variable -Name "$($ListType)Template" -ValueOnly -Scope Global) + + If(!(Test-Path -Path $PathList) -or !(Test-Path -Path $PathTemplate)){ + return + } + $List = @{ } + $Key = $ListMainKey.$ListType + $List.$Key = @( ) + Foreach($Item in $Template){ + If($Item.Selected){ + $List.$Key += $Item.$Key + } + } + + $Template | ConvertTo-Json | Out-File -FilePath $PathTemplate -Encoding UTF8 -Force -ErrorAction Ignore + $List | ConvertTo-Json | Out-File -FilePath $PathList -Encoding UTF8 -Force -ErrorAction Ignore +} + +Function Save-Features { + $FeaturesToDisable = @() + $FeaturesToEnable = @() + + Foreach($Feature in $Global:FeaturesTemplate){ + If($Feature.State -eq "Enabled" -and $Feature.OriginalState -eq "Disabled"){ + $FeaturesToEnable += $Feature.FeatureName + } + If($Feature.State -eq "Disabled" -and $Feature.OriginalState -eq "Enabled"){ + $FeaturesToDisable += $Feature.FeatureName + } + } + $Global:FeaturesTemplate | ConvertTo-Json | Out-File -FilePath "$RootPath\RemovalTemplates\FeaturesTemplate.json" -Encoding UTF8 -Force -ErrorAction Ignore + @{FeatureName = $FeaturesToEnable} | ConvertTo-Json | Out-File -FilePath "$($OO_Lists_Path)FeaturesToEnable\FeaturesToEnableList.json" -Encoding UTF8 -Force -ErrorAction Ignore + @{FeatureName = $FeaturesToDisable} | ConvertTo-Json | Out-File -FilePath "$($OO_Lists_Path)FeaturesToDisable\FeaturesToDisableList.json" -Encoding UTF8 -Force -ErrorAction Ignore +} +Function Save-Services { + $Services = @() + Foreach($Service in $Global:ServicesTemplate){ + If($Service.OriginalStart -ne $Service.Start) { + $Services += @{ + name = $Service.Name + start = $Service.Starts.IndexOf($Service.Start) + description = $Service.Description + } + } + } + $Global:ServicesTemplate | ConvertTo-Json | Out-File -FilePath "$RootPath\RemovalTemplates\ServicesTemplate.json" -Encoding UTF8 -Force -ErrorAction Ignore + @{Services = $Services} | ConvertTo-Json | Out-File -FilePath "$($OO_Lists_Path)Services\ServicesAdvanced.json" -Encoding UTF8 -Force -ErrorAction Ignore +} + +Function GenerateControlXaml { + param ($Control) + + $XAML = $InputLayoutXAML + $InputControl = Switch ($Control.Type) { + "ComboBox" { + $ComboBoxXAML + } + "Switch" { + $CheckBoxXAML + } + default {""} + } + + $InputControl = $InputControl.Replace("{Name}", $Control.Name) + $InputControl = $InputControl.Replace("{Label}", $Control.Label) + + Switch ($Control.Type) { + "ComboBox" { + $InputControl = $InputControl.Replace("{Value}", $($Control.Values.IndexOf(($Configuration.($Control.Binding))))) + $InputControl = $InputControl.Replace("{Items}", $($(Foreach($Value in $Control.Values){" + + "}) -join "`n")) + } + "Switch" { + $InputControl = $InputControl.Replace("{Value}", "{Binding Configuration.$($Control.Binding)}") + } + } + + $InputControl = $InputControl.Replace("{Tooltip}", $(If($Control.Description){ $Control.Description } Else {""})) + + $XAML = $XAML.Replace("{Input}", $InputControl) + + return $XAML +} + +Function Set-ControlsVisibility { + $ImageInfo = (Get-Content -Raw -Path "$RootPath\image_info.json" -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop) + If(!$ImageInfo -or !$ImageInfo.Build){ + return + } + $ConfigurationDef.PSObject.Properties | ForEach-Object { + Foreach($Control in $_.Value.Controls) { + If($Control.Restrictions -and $Control.Restrictions.Count -gt 0){ + $valid = $true + Foreach($Restriction in $Control.Restrictions) { + If($Restriction.Build -gt 0) { + Switch ($Restriction.Criteria) { + "min" { + If($ImageInfo.Build -gt 0 -and $ImageInfo.Build -lt $Restriction.Build) + { + $valid = $false + break + } + } + "max" { + If($ImageInfo.Build -gt 0 -and $ImageInfo.Build -gt $Restriction.Build) + { + $valid = $false + break + } + } + } + } + } + $ControlWPF = $Window.FindName($Control.Name) + $ControlWPF.Visibility = $(If (!$valid) {"Collapse"} Else {"Visible"}) + Switch($Control.Type) { + "Switch" { + $ControlWPF.IsChecked = $false + } + "ComboBox" { + $ControlWPF.SelectedIndex = 0 + } + } + } + } + } +} + +Function GenerateTabLayout { + param ([string]$Content, [string]$TabHeader, [string]$Name, [switch]$NoScroll) + $XAML = $(If($NoScroll.IsPresent) {$TabLayoutXAML} Else {$TabScrollXAML}) + $XAML = $XAML.Replace("{TabContent}", $Content) + $XAML = $XAML.Replace("{TabHeader}", $TabHeader) + $XAML = $XAML.Replace("{Name}", $Name) + return $XAML +} + +Function GenerateMainConfigTab { + $XAML = $MainConfigTabXAML + $TabXAML = GenerateTabLayout -Content $XAML -TabHeader "General" -Name "GeneralTab" + $Cols = @{} + $ConfigurationDef.PSObject.Properties | ForEach-Object -Process { + $ControlsXAML = "" + Foreach ($Control in $_.Value.Controls) { + $ControlXAML = GenerateControlXaml -Control $Control + If($ControlXAML.Trim() -ne "") { + $ControlsXAML = $ControlsXAML + $ControlXAML + } + } + If($ControlsXAML -eq ""){ + $ControlsXAML = " + " + } + $SectionXAML = $MainConfigGroupBoxXAML + $SectionXAML = $SectionXAML.Replace("{Header}", $_.Value.Label) + $SectionXAML = $SectionXAML.Replace("{Content}", $ControlsXAML) + If(!$Cols[$_.Value.Column]){ + $Cols[$_.Value.Column] = "" + } + $Cols[$_.Value.Column] += $SectionXAML + } + $ColsXAML = "" + foreach($i in $Cols.keys){ + $ColsXAML += " + + $($Cols[$i]) + + " + } + $TabXAML = $TabXAML.Replace("{ColsXAML}", $ColsXAML) + $TabXAML = $TabXAML.Replace("{Cols}", $Cols.Count) + return $TabXAML +} + +Function GenerateListTab { + param([string]$ListType, [string]$Header) + If(!($Configuration.$ListType)){ + return "" + } + $Type = $($Configuration.$ListType).Trim() + $Type = $Type.substring(0,1).toupper()+$Type.substring(1).tolower() + $ListTypeSelectedIndex = $($RemovalTypes.IndexOf($Type)) + If($ListTypeSelectedIndex -lt 0){ + $ListTypeSelectedIndex = 0 + } + $TabXAML = $ListRemovalTabXAML.Replace("{ListType}", $ListType) + $TabXAML = $TabXAML.Replace("{ListTypeSelectedIndex}", $ListTypeSelectedIndex) + $TabXAML = $TabXAML.Replace("{Columns}", $($(Foreach($Value in $ListColumns.$ListType){" + + "}) -join "`n")) + return (GenerateTabLayout -NoScroll -Content $TabXAML -TabHeader $Header -Name "$($ListType)Tab") +} + +Function GenerateListComboTab { + param([string]$ListType, [string]$Header) + $TabXAML = $ListRemovalComboTabXAML.Replace("{ListType}", $ListType) + $Columns = @() + Foreach($Column in $ListColumns.$ListType){ + $Columns += " + + " + } + Foreach($Column in $ListColumnsComboBox.$ListType){ + $Columns += " + + + + + + + + " + } + $TabXAML = $TabXAML.Replace("{Columns}", $Columns) + return (GenerateTabLayout -NoScroll -Content $TabXAML -TabHeader $Header -Name "$($ListType)Tab") +} + +Function GenerateOutputTab { + $Content = $OutputTabXAML + return (GenerateTabLayout -NoScroll -Content $Content -TabHeader "Output" -Name "OutputTab") +} + + +Function GenerateCustomRegistryTab { + $Content = $CustomRegistryTabXAML + return (GenerateTabLayout -NoScroll -Content $Content -TabHeader "Custom Registry" -Name "CustomRegistryTab") +} + + +$TabsXAML = " +$(GenerateMainConfigTab) +$(GenerateListTab -ListType "WindowsApps" -Header "Windows Apps") +$(GenerateListTab -ListType "SystemApps" -Header "System Apps") +$(GenerateListTab -ListType "Capabilities" -Header "Capabilities") +$(GenerateListTab -ListType "Packages" -Header "Packages") +$(GenerateListComboTab -ListType "Features" -Header "Features") +$(GenerateListComboTab -ListType "Services" -Header "Services") +$(GenerateCustomRegistryTab) +$(GenerateOutputTab) +" +$LayoutXAML = $LayoutXAML.Replace("{Tabs}", $TabsXAML) + +[xml]$XAML = @" +$LayoutXAML +"@ + +$Reader = (New-Object System.Xml.XmlNodeReader $XAML) +$Window = [Windows.Markup.XamlReader]::Load($Reader) + +If (!$Window) { + Exit +} + +$Window.Add_Closing({ + CleanVars + StopOO +}) + +$Window.Icon = "$RootPath\setup.ico" +$BrowseSourcePathButton = $Window.FindName("Browse_SourcePath") +$BrowseOutputPathButton = $Window.FindName("Browse_OutputPath") +$ProcessButton = $Window.FindName("ProcessButton") +$CancelButton = $Window.FindName("CancelButton") +$PopulateButton = $Window.FindName("PopulateButton") +$SelectUSB = $Window.FindName("SelectUSB") +$SelectedUSB = $Window.FindName("SelectedUSB") +$FlashToUSB = $Window.FindName("FlashToUSB") +$SourcePath = $Window.FindName("SourcePath") +$OutputPath = $Window.FindName("OutputPath") +$OutputTab = $Window.FindName("OutputTab") +$Console = $Window.FindName("Console") +$CustomRegistry = $Window.FindName("CustomRegistry") +$GeneralTab = $Window.FindName("GeneralTab") +$WindowsAppsTab = $Window.FindName("WindowsAppsTab") +$SystemAppsTab = $Window.FindName("SystemAppsTab") +$CapabilitiesTab = $Window.FindName("CapabilitiesTab") +$PackagesTab = $Window.FindName("PackagesTab") +$FeaturesTab = $Window.FindName("FeaturesTab") +$ServicesTab = $Window.FindName("ServicesTab") +$CustomRegistryTab = $Window.FindName("CustomRegistryTab") + +Set-ControlsVisibility + +Foreach($ListType in $ListTypes) { + New-Variable -Name "$($ListType)ListView" -Value $Window.FindName("$($ListType)ListView") + New-Variable -Name "$($ListType)ListFilter" -Value $Window.FindName("$($ListType)ListFilter") + New-Variable -Name "$($ListType)ListType" -Value $Window.FindName("$($ListType)ListType") + New-Variable -Name "$($ListType)SelectAll" -Value $Window.FindName("$($ListType)SelectAll") + New-Variable -Name "$($ListType)SelectNone" -Value $Window.FindName("$($ListType)SelectNone") +} + +Function SetControlsAccess { + param($Enabled) + $GeneralTab.IsEnabled = $Enabled + $WindowsAppsTab.IsEnabled = $Enabled + $SystemAppsTab.IsEnabled = $Enabled + $CapabilitiesTab.IsEnabled = $Enabled + $PackagesTab.IsEnabled = $Enabled + $FeaturesTab.IsEnabled = $Enabled + $ServicesTab.IsEnabled = $Enabled + $CustomRegistryTab.IsEnabled = $Enabled + $ProcessButton.IsEnabled = $Enabled + $CancelButton.IsEnabled = -not $Enabled + $PopulateButton.IsEnabled = $Enabled + $FlashToUSB.IsEnabled = $Enabled + $SelectUSB.IsEnabled = $Enabled + $SourcePath.IsEnabled = $Enabled + $BrowseSourcePathButton.IsEnabled = $Enabled + $OutputPath.IsEnabled = $Enabled + $BrowseOutputPathButton.IsEnabled = $Enabled +} + +Function Save-Configuration { + foreach($ListType in $ListTypes){ + If($Configuration.$ListType -and $ListTypesNoRemoval.IndexOf($ListType) -ge 0){ + continue + } + $Control = $Window.FindName("$($ListType)ListType") + If($Configuration.$ListType -and $Control){ + If($RemovalTypes.IndexOf($Control.SelectedItem.Content) -ge 0){ + $Configuration.$ListType = $Control.SelectedItem.Content + } Else { + $Configuration.$ListType = $RemovalTypes[0] + } + } + } + $Configuration.Services = "Advanced" + $Configuration.FeaturesToEnable = "List" + $Configuration.FeaturesToDisable = "List" + $Configuration | ConvertTo-Json | Out-File -FilePath $Configuration_path -Encoding UTF8 -Force -ErrorAction Ignore +} + +Function SetError { + param([string]$Err) + $OutputTab.IsSelected = $true + WriteToConsole -Text "`nError GUI: $Err" -Append +} + +Function WriteToConsole { + param([string]$Text, [switch]$Append) + + If($Append){ + $Console.Text += $Text + } Else { + $Console.Text = $Text + } + + $Console.ScrollToEnd() +} + +Function RunOO { + param([switch]$populateTemplates) + $Global:populateTemplates = $populateTemplates + Try{ + Save-Configuration + $OutputTab.IsSelected = $true + SetControlsAccess -Enabled $false + $Global:OO_GUI_Job = Start-Process powershell -WindowStyle Hidden -argument "Set-ExecutionPolicy Bypass -Scope Process -Force; & '$($OO_Root_Path)Start-Optimize.ps1' -GUI -FlashUSBDriveNumber $Global:OO_GUI_FlashUSBDriveNumber $(If($populateTemplates) {"-populateTemplates"} Else {''}) *>> '$($ConsoleSTDOutPath)'" -Verb RunAs -PassThru + $Global:OO_GUI_Timer.Start() + } Catch { + SetError -Err $Error[0] + SetControlsAccess -Enabled $true + $Global:OO_GUI_Timer.Stop() + If(Test-Path -path "$ConsoleSTDOutPath"){ + Remove-Item -Path "$ConsoleSTDOutPath" + } + } +} + +Function Kill-Tree { + Param([int]$ppid) + Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq $ppid } | ForEach-Object { Kill-Tree $_.ProcessId } | Stop-Process -Id $ppid +} + +Function StopOO { + If($Global:OO_GUI_Job) { + Kill-Tree $Global:OO_GUI_Job.Id + Stop-Process $Global:OO_GUI_Job + } +} + +$ProcessButton.Add_Click({ + RunOO +}) + +$CancelButton.Add_Click({ + $continue = [System.Windows.MessageBox]::Show("Are you sure you want to cancel the processing job?", "Cancel processing", 'YesNo') + If($continue -eq 'Yes') { + StopOO + } +}) + +$PopulateButton.Add_Click({ + RunOO -populateTemplates +}) + +$Window.DataContext = [PSCustomObject]@{ + Configuration = [PSCustomObject]$Configuration +} + +If(Test-Path -Path $Configuration.SourcePath) { + $SourcePath.Text = $Configuration.SourcePath + SetControlsAccess -Enabled $true +} + +$OutputPath.Text = $Configuration.OutputPath +$Configuration.FlashToUSB = "Off" + +$SelectedFlashToUSBIndex = @("UEFI", "Legacy").IndexOf($Configuration.FlashToUSB) +If($SelectedFlashToUSBIndex -ge 0) { + $FlashToUSB.SelectedIndex = $SelectedFlashToUSBIndex +} + +$BrowseSourcePathButton.Add_Click({ + $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ + InitialDirectory = [Environment]::GetFolderPath('Desktop') + Filter = 'All allowed types|*.wim;*.swm;*.iso;*.esd;*.WIM;*.SWM;*.ISO;*.ESD' + Multiselect = $false + AddExtension = $true + CheckPathExists = $true + } + + $null = $FileBrowser.ShowDialog() + + If($FileBrowser.FileName -and $FileBrowser.FileName -ne $SourcePath.Text){ + $SourcePath.Text = Get-Item -Path $FileBrowser.FileName + } +}) + +$BrowseOutputPathButton.Add_Click({ + $SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog + $SaveFileDialog.InitialDirectory = [Environment]::GetFolderPath('Desktop') + $SourceExtension = (Get-Item $SourcePath.Text).Extension + $SaveFileDialog.Filter = "$($SourceExtension) files (*$($SourceExtension))| *$($SourceExtension)" + If($SaveFileDialog.ShowDialog() -eq 'Ok'){ + $OutputPath.Text = $SaveFileDialog.FileName + } +}) + +$SourcePath.Add_TextChanged({ + $Enabled = ("" -ne $SourcePath.Text.Trim() -and (Test-Path -Path $SourcePath.Text.Trim())) + $Configuration.SourcePath = $SourcePath.Text.Trim() + Save-Configuration + SetControlsAccess -Enabled $true + If($Enabled){ + RunOO -populateTemplates + } +}) + +$OutputPath.Add_TextChanged({ + $Configuration.OutputPath = $OutputPath.Text.Trim() + Save-Configuration +}) + +Foreach($ListType in $ListTypes) { + + $SaveConfiguration = [ScriptBlock]::Create((Get-Item function:Save-Configuration).Definition) + $SaveList = [ScriptBlock]::Create((Get-Item function:Save-List).Definition) + + $ListView = Get-Variable -Name "$($ListType)ListView" -ValueOnly + + If(!$ListView){ + Continue + } + + $ListTemplate = (Get-Variable -Name "$($ListType)Template" -ValueOnly -Scope Global) + $ListView.ItemsSource = $ListTemplate + + If($ListTypesNoRemoval.IndexOf($ListType) -eq -1){ + (Get-Variable -Name "$($ListType)SelectAll" -ValueOnly).Add_Click({ + $ListView.SelectAll() + $ListView.Focus() + }.GetNewClosure()) + (Get-Variable -Name "$($ListType)SelectNone" -ValueOnly).Add_Click({ + $ListView.UnselectAll() + $ListView.Focus() + }.GetNewClosure()) + (Get-Variable -Name "$($ListType)ListType" -ValueOnly).Add_SelectionChanged({ + $SaveConfiguration.Invoke() + $ListView.Focus() + }.GetNewClosure()); + $ListView.Add_SelectionChanged({ + $SaveList.Invoke($ListType) + }.GetNewClosure()); + } + + $ListFilter = Get-Variable -Name "$($ListType)ListFilter" -ValueOnly + $ListFilter.Add_TextChanged({ + $ListTemplate = (Get-Variable -Name "$($ListType)Template" -ValueOnly -Scope Global) + If("" -eq $ListFilter.Text){ + $ListView.ItemsSource = [PSCustomObject]$ListTemplate + $ListFilter.Focus() + return + } + $Filtered = @() + foreach($Item in $ListTemplate){ + foreach($prop in $Item.PsObject.Properties) + { + If($prop.Value -like "*$($ListFilter.Text)*") { + $Filtered += $Item + Break + } + } + } + $ListView.ItemsSource = [PSCustomObject]$Filtered + $ListFilter.Focus() + }.GetNewClosure()) +} + +$TimerTick = { + If(Test-Path -Path "$ConsoleSTDOutPath"){ + WriteToConsole -Text (Get-Content -Path "$ConsoleSTDOutPath" -Raw -Encoding utf8) + [Windows.Input.InputEventHandler]{ $Window.UpdateLayout() } + } + If($null -ne $Global:OO_GUI_Job.ExitCode){ + $Global:OO_GUI_Timer.Stop() + SetControlsAccess -Enabled $true + If(Test-Path -Path "$ConsoleSTDOutPath"){ + Remove-Item -Path "$ConsoleSTDOutPath" + } + Import-Templates + foreach($ListType in $ListTypes) { + $ListView = (Get-Variable -Name "$($ListType)ListView" -ValueOnly) + $ListView.ItemsSource = (Get-Variable -Name "$($ListType)Template" -ValueOnly -Scope Global) + } + Set-ControlsVisibility + Save-Configuration + WriteToConsole -Text "`nFinished" -Append + } +} +$Global:OO_GUI_Timer.Add_Tick($TimerTick) + + +$ConfigurationDef.PSObject.Properties | ForEach-Object { + Foreach($Config in $_.Value.Controls) { + $Control = $Window.FindName($Config.Name) + If($Control){ + Switch($Config.Type) { + "Combobox" { + $SaveConfiguration = [ScriptBlock]::Create((Get-Item function:Save-Configuration).Definition) + $Control.Add_SelectionChanged({ + If($Config.Values.IndexOf($args[0].SelectedItem.Content) -gt -1){ + $Configuration.($Config.Binding) = $args[0].SelectedItem.Content + } + $SaveConfiguration.Invoke() + }.GetNewClosure()) + } + "Switch" { + $Control.Add_Checked({ + Save-Configuration + }) + $Control.Add_UnChecked({ + Save-Configuration + }) + } + } + } + } +} + +$Window.FindName("FeaturesListView").Add_MouseLeave({ + Save-Features +}) +$Window.FindName("ServicesListView").Add_MouseLeave({ + Save-Services +}) + +$FlashToUSB.Add_SelectionChanged({ + If($Global:OO_GUI_FlashUSBDriveNumber -ge 0){ + $Configuration.FlashToUSB = $FlashToUSB.SelectedItem.Content + } Else { + $Configuration.FlashToUSB = "Off" + } + Save-Configuration +}) +$SelectUSB.Add_Click({ + $SelectedUSB.IsEnabled = $false + $SelectedUSB.Visibility = "Collapsed" + $USBDrives = Get-Disk | Where-Object BusType -eq USB + If($USBDrives.Count -eq 0) { + [System.Windows.MessageBox]::Show('No USB drives found') + return + } + $USBDrive = $USBDrives | Out-GridView -Title 'Select USB Drive to Format' -OutputMode Single + If($USBDrive){ + $SelectedUSB.Content = $USBDrive.FriendlyName + $Global:OO_GUI_FlashUSBDriveNumber = $USBDrive.Number + $Configuration.FlashToUSB = $FlashToUSB.SelectedItem.Content + Save-Configuration + $SelectedUSB.IsEnabled = $true + $SelectedUSB.Visibility = "Visible" + } +}) + +If(Test-Path -Path $CustomRegistryPath){ + $CustomRegistry.Text = Get-Content -Path $CustomRegistryPath -Raw -ErrorAction Ignore +} + +$CustomRegistry.Add_MouseLeave({ + If($CustomRegistry.Text.Trim() -ne "Please input custom registry tweaks here."){ + $CustomRegistry.Text.Trim() | Out-File -Path "$($OO_Root_Path)\Content\CustomRegistry.reg" + } +}); + +$Window.FindName("TabControl").Add_SelectionChanged({ + $Window.UpdateLayout() + If($WindowsAppsTab.IsSelected){ + $Window.FindName("WindowsAppsListView").Focus() + } Elseif ($SystemAppsTab.IsSelected){ + $Window.FindName("SystemAppsListView").Focus() + } Elseif ($CapabilitiesTab.IsSelected){ + $Window.FindName("CapabilitiesListView").Focus() + } Elseif ($PackagesTab.IsSelected){ + $Window.FindName("PackagesListView").Focus() + } +}) + +Save-Configuration + +[Void]$Window.ShowDialog() + diff --git a/Src/GUI/XAML/CheckBox.xaml b/Src/GUI/XAML/CheckBox.xaml new file mode 100644 index 0000000..8e73c7e --- /dev/null +++ b/Src/GUI/XAML/CheckBox.xaml @@ -0,0 +1,20 @@ + + {Label} + + + + + {Tooltip} + + \ No newline at end of file diff --git a/Src/GUI/XAML/ComboBox.xaml b/Src/GUI/XAML/ComboBox.xaml new file mode 100644 index 0000000..dc0e541 --- /dev/null +++ b/Src/GUI/XAML/ComboBox.xaml @@ -0,0 +1,13 @@ +