Hello, everything is in the title, what do you think of this manipulation, I am trying to reduce the winxs directory 1. Firstly, open the command prompt as administrator.2. Then, stop and disable Windows Installer and Windows Module Installer services: sc stop msiserver sc stop TrustedInstaller sc config msiserver start= disabled sc config TrustedInstaller start= disabled 3. Let us backup the Access Control Lists (ACLs) assigned to the files and folders in the WinSxS directory using the built-in icacls tool. A backup copy of an ACL is a plain text file that lists all files and directories and the NTFS permissions assigned to them (later this file will be needed to restore the original ACLs): icacls “%WINDIR%\WinSxS” /save “%WINDIR%\WinSxS_NTFS.acl” /t 4. Assign us as an owner of the WinSxS folder and all its subfolders: takeown /f “%WINDIR%\WinSxS” /r 5. Grant our account full control permissions on the WinSxS directory: Code: icacls “%WINDIR%\WinSxS” /grant “%USERDOMAIN%\%USERNAME%”:(F) /t 6. We can now compress files in the WinSxS directory using the compact command. Because some of the files can be used by Windows, we need to specify the /i option. Otherwise, compression will stop at the first locked file (in Windows 10, we can use more advanced LZX compression): compact /s:”%WINDIR%\WinSxS” /c /a /i * 7. Restore the owner of the WinSxS directory back to TrustedInstaller: icacls “%WINDIR%\WinSxS” /setowner “NT SERVICE\TrustedInstaller” /t 8. Restore the original ACLs for the WinSxS folder items using the ACL backup file we created earlier: icacls “%WINDIR%” /restore “%WINDIR%\WinSxS_NTFS.acl” 9. Restore the default startup type for the Windows Installer and Windows Module Installer services: sc config msiserver start= demand sc config TrustedInstaller start= demand Now check the current size of the WinSxS folder.
with aveyo run as ti method. Code: @cls @echo off >nul chcp 437 Title Compact OS Tool setlocal enabledelayedexpansion cd /d %~dp0 set "fp=%~f0" :::: check if we running under system Rights whoami|>nul findstr /i /c:"nt authority\system" && ( call :Run_AS_TI %* echo. & pause & exit /b ) shift & set "args=%*" call :RunAsTI cmd /c call "%fp%" %args% exit :Run_AS_TI cls echo: set folder_list=^ ,"%windir%\winsxs"^ ,"%windir%\system32"^ ,"%windir%\SysWOW64"^ ,"%ProgramFiles%\WindowsApps" for %%$ in (%folder_list:;=,%) do ( echo Compress Folder: %%$ >nul compact /c /s:%%$ /exe:LZX /q /i ) echo: goto :eof #: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:
That's really overkill. And also, it compress using only the LZX compression, which doesn't inherit the compressed status A way better approach is. #1 First compress your whole OS partition using the good old NTFS compression Just launch a 3d party file manager like xy explorer, launch it as trusted installer and compress the whole partition (preferably starting from a parallel OS or WinPE bootable media) #2 Capture the partition using wimlib-capture #3 Format the partition and restore the wim using wimlib-apply using the switch -compact=LZX #4 Given the process breaks the bcd entries, use bcdboot or bootice or easybcd, to re-add your OS to bcd. This way all immutable files will be LZX compressed, while anything that changes will be still compressed although using the standard NTFS compression. No need to touch ACLs, no need to mess with permissions ownership and alike, and if you are on SSD the system will be also faster (if you are on HDD just avoid compression)
Yes and no. I mean, OS "installation" is matter of the past. All you need is starting from #3, no matter if you need compression or not. Just learn to deploy whenever you need a fresh install. (I mean use the ISO and setup.exe just for in place upgrades) That said if you start from #3 and use a normal install media you will get your shiny fresh and small OS. But this way the OS will be compressed only using the LZX compression, which means very small initial footprint but the OS will grow fast because the LZX compression doesn't recompress the compressed files (open a compressed file, change a single bit on it, save it, and your file will be magically decompressed). What you can do is: take the install.wim, mount it and compress it using the standard NTFS compression (use the xy explorer + nsudo method described above) Then unmount the install.wim (committing the changes), and (if you want) replace it in the ISO. This way any installation/deployment made using it will be NTFS compressed (which is already a great thing, 1.6 x less space taken and a faster OS on SSD). But, if you deploy that install.wim using wimlib-apply with the --compact=LZX switch, the OS will be BOTH NTFS and LZX compressed. The initial compression ratio will be between 2.5 and 3.0x (aka a fresh x64 install will take less than 6GB instead of ~16GB, and a x86 install will take less than 4GB instead of ~10GB. Using the OS (installing new SW, cumulative updates and so on) that size obviously will grow, but will grow way less than a system which is compressed only with the modern LZX compression. P.S. before someone ask, no the two compression method doesn't step each other feet. Because the old NTFS compression was made purposely to not try to recompress an already compressed file
should be useful https://forums.mydigitallife.net/threads/cmd-reducing-windows-8-10-11-size-by-half-v1-01.86261/
The compact command, while compresses on LZX (or Xpress-Something) removes the ntfs compression making the whole operation almost useless. Unless you repeat it each time you apply an LCU or each time you install a big program. The truth is that the modern compression methods are half backed, i guess MS did it for backward compatibility reasons, but as a matter of fact the 1993 or so NTFS compression is way more useful than the LZX compression (if used alone).
the ntfs compression is not compact ? i thought kernel needs this specific compression method to be able to read on-the-fly
Compact is the command the NTFS copmpression is a native filesystem feature which is there since Winnt 3.x. Given the CPU and the RAM of the time it was developed as a low taxing method. Which means today it requires practically zero effort by the CPU. The compact command was used to manage it, but it's also accessible from the GUI. Since W8.1 the four new compression methods were introduced, but they are not integrated in the filesystem. They are a layer on top of it (like the deduplication). That method was then perfected in Win10. BUT There isn't any GUI to manage it, not there is any way to keep the compressed status after an edit, nor any way to inherit the compressed status ftom the parent folder or disk. the only tools that manage it are the compact command (which accepts more switches), and DISM (and its better open source cousin wimlib). AFAIK there isn't any way (other than my method) to keep both the NTFS compression flag AND the LZX (or Xpress) compression. But maybe I'm missing something, if anyone has a better method than mine, I'm all ears. P.S. the screenshot above is a full Server 2016 installation, no package removed and all the SW I use installed, Including VMware, VBox, WMC, various TV server SW, OFFICE Starter, and so on. It takes 8GB, half of what Server 2016 would normally requires W/O any additional SW installed. P.S.2 Althoug the method is fully working only on W10, it can be extended to W7/W8/W8.1 (x86 and AMD64) all you need is the wofadk.sys driver (winntsetup.exe can automate the procedure)
This command is the command-line version of the NTFS file system compression feature. Which by all means says .. it's a ntfs compression for specific folders
[Pedantic mode=on] This command WAS the command meant to manage the NTFS file system compression feature now it manages both the NTFS compression feature and the "Compact OS" compression. And both are not by folder, but also by single file or by whole disk [Pedantic mode=off] To put it more colloquially the Compact OS feature is something which is half way between the NTFS native compression and something like a file compressor like .ZIP or .CAB.