Thursday, February 2, 2023

Huge WindowsApps folder in 2023

 In may 2022 we did already talk about huge WindowsApps folder under Windows 10.

All things are still valid in 2023, and also for Windows 11, with the exception that there is an enhanced cleanup script available from the TenForum which also handles folder ownership stuff and can delete all orphaned folders.

 

As a reference, I have a copy of the script here, in case the other forum would close/disappear some time in the future.

 

::::::::::::::::::::::::::::::
:: By Einstein1969 for www.tenforum.com
::
%= CleanWA =% @set "Version=0.1.4.2 BETA"
::
:: Detect orphaned dirs in %ProgramFiles%\WindowsApps, check for integrity/consistency
::
:: Requirements: Save to UTF-8. Use Lucida Console Font in CMD window. Run with double click over icon script.
::         Windows 10 version 1511 (build number 10586) onward
::
:: history:
::   10/08/2022 0.1.4.2 BETA  added some stuff for taking correct ownership with different languages
::   10/08/2022 0.1.4.1 BETA  added some hints to take ownership  
::   04/02/2022 0.1.4 BETA    fix some minor bug and aesthetic improvements
::     /10/2021 0.1.4 BETA    fix bug for elevated char ;,=() &^
::   29/09/2021 0.1.3 BETA    Search for applications that do not have InstallLocation set.
::                            Enable support for Unicode UTF-8 and VT-ANSI
::   25/09/2021 0.1.2 BETA    removed debug, added run as administrator , thanks Matthew Wai
::   25/09/2021 0.1.1 BETA    add debug instruction for "file not found" bug/error.
::
:: ref: https://www.tenforums.com/tutorials/4689-uninstall-apps-windows-10-a.html
:: ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off & setlocal EnableDelayedExpansion&color 1f&title CleanWA %Version%

Rem Choice the WindowsApps (WA) directory to check.
set "WA=%ProgramW6432%\WindowsApps"

set PromptLine=
copy /y nul "%TEMP%\yesnoall#.tmp" >nul
for /f "tokens=2* delims=#" %%A in ( '^<nul copy /-y nul "%TEMP%\yesnoall#.tmp"'
  ) do set PromptLine=%%A
del "%TEMP%\yesnoall#.tmp"
set PromptLine=%PromptLine: =%& rem delete spaces (for russian)
for /f "tokens=2-7 delims=[(/)]" %%A in ( "%PromptLine%"
  ) do if "%%~E" == "" ( set ans_yes=%%A& set ans_no=%%B& set ans_all=%%C
  ) else ( set ans_yes=%%A& set ans_no=%%C& set ans_all=%%E
)
set ans_y=%ans_yes:~0,1%& set ans_n=%ans_no:~0,1%& set ans_a=%ans_all:~0,1%

echo %ans_yes%, %ans_no%, %ans_all%
echo %ans_y%, %ans_n%, %ans_a%

Rem Check for Run as administrator.
call :Restart_as_Administrator %1

Call :video_setting

Rem check for permission on WA
if not exist "%WA%\." echo( & echo Error: Problem accessing "%WA%" & goto :the_end

echo(
echo    Analyze "%WA%"
echo(

Echo      Check for applications that do not have "InstallLocation" set.
echo(

rem create list of registered app
> "%tmp%\CleanWA.RegisteredApps.tmp.txt"  ^
 (
    rem exclude "system" applications in c:\windows folder
    powershell -Command "Get-AppxPackage -AllUsers | ? { $_.SignatureKind -ne 'System' } | sort -property {$_.InstallLocation+' '} | ForEach-Object {'{0,-40}  {1,-20}  {2}' -f $_.name,$_.version,$_.InstallLocation}"
 )

type nul: > "%tmp%\CleanWA.RegisteredApps_good.tmp.txt"
type nul: > "%tmp%\CleanWA.RegisteredApps_NO_good.tmp.txt"
FOR /f "usebackq tokens=1,2,*" %%a in ("%tmp%\CleanWA.RegisteredApps.tmp.txt") do (
    if "%%c" equ "" (
        echo(    %CSI%7m? Warning: Registered app "%%a" does not have a "InstallLocation" set/defined. ?%CSI%27m
        echo(
        echo Rem Warning: Registered app "%%a" does not have a "InstallLocation" set/defined. >> "%tmp%\CleanWA.RegisteredApps_NO_good.tmp.txt"
    ) else echo(%%a %%b %%c >> "%tmp%\CleanWA.RegisteredApps_good.tmp.txt"
)

echo     v check finished.
echo(

echo      Detect orphaned dirs
echo(

type nul > "%tmp%\CleanWA.report_orphans.tmp.txt"
set "dn=0" & rem number of folders/directories
set /A "Size=0, Totsize=0,dirsO"
FOR /f "tokens=*" %%z IN ('dir /b /o:n "%WA%"') DO (
  set /a "dn+=1"
 
  FOR /f "tokens=1-4" %%g in ('dir /S /W /-C "%WA%\%%z"') do (set "oldlineSize=!line!" & set line=%%i)
  call :pad dn 4
  set /A "size=!oldlineSize:~0,-4!+0, sizeMB=size/105"
  echo        !dn! - Searching for folder:
  echo                "%%z" (about !SizeMB! MBytes^) %CSI%0K

  set "found="
  for /f "usebackq tokens=1,2,*" %%a in ("%tmp%\CleanWA.RegisteredApps_good.tmp.txt") do if not defined found (
        rem echo        Pkg. InstallLocation "%%c" %CSI%0K %RI%
        set _V_=%%z
        set v1="x!_V_:%%a_%%b=!x"
        set v2="x!_V_!x"
        if !v1! NEQ !v2! (
        set Found=1
        rem echo(      %CSI%102m? Found an app that use this folder ?%CSI%44m : %CSI%102m"%%a"%CSI%44m version: "%%b" %CSI%0K
    )
  )

  if defined found (
    echo(%RI%%RI%%RI%
  ) else (
    rem check for unknown folder/dir
    rem known:_x64_, _x86_, _neutral_ .... others?
        set v1="x!_V_:_x64_=!x"
        set v2="x!_V_!x"
    set "OK=N"
        if !v1! NEQ !v2! set "OK=Y"
        set v1="x!_V_:_x86_=!x"
    if !v1! NEQ !v2! set "OK=Y"
    set v1="x!_V_:_neutral_=!x"
    if !v1! NEQ !v2! set "OK=Y"

    if !OK! NEQ Y (
        echo(
        echo       %CSI%43m? No Match folder: "%%z" ?%CSI%44m%CSI%0K
        echo(
        echo(
        ping -n 2 127.0.0.1 >nul
    ) else (
        echo(
        echo       %CSI%101m? orphans folder! ?%CSI%44m%CSI%0K
        echo(
        echo(
        rem why 105? 1024*1024/10000 ~ 105
        set /A "Totsize+=size, TotsizeMB=Totsize/105, dirsOrphans+=1"
        title CleanWA %Version% [Tot. space orphans: about !TotsizeMB! MB] [dirs/folder orphans: !dirsOrphans!]
        (
          echo rem folder "%%z" (about !oldlineSize! Bytes^, about !SizeMB! MBytes^)
          echo takeown /F "%WA%\%%z" /r /d %ans_y%
          echo icacls "%WA%\%%z" /t /grant %USERNAME%:F
          echo RD /Q /S "%WA%\%%z"
          echo(
                ) >> "%tmp%\CleanWA.report_orphans.tmp.txt"
    )
  )
  rem pathping 127.0.0.1 -n -q 1 -p 100 >nul
)
echo(
echo(
echo(
echo     v check finished.
echo(
echo dirs/folder orphans: !dirsOrphans!
echo(
echo Tot. space orphans: about !TotsizeMB! MB
echo(

>nul: copy /a "%tmp%\CleanWA.RegisteredApps_NO_good.tmp.txt" + /a "%tmp%\CleanWA.report_orphans.tmp.txt" "%tmp%\CleanWA.report.tmp.txt"

echo coping Report/script "%tmp%\CleanWA.report.tmp.txt" for offline delete in \Users\Public
copy "%tmp%\CleanWA.report.tmp.txt" \Users\Public
echo(
pause

start notepad "\Users\Public\CleanWA.report.tmp.txt"

:the_end
:: pause if double clicked on instead of run from command line.
echo %cmdcmdline% | findstr /I /L %comspec% >nul 2>&1
if %errorlevel% == 0 echo( & pause
exit /B 0
goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::   SUBROUTINE   ::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Restart_as_Administrator
(Fsutil Dirty Query %SystemDrive%>Nul)&&(
        if "%1" neq "admin" (
        start /MAX %~f0 admin
        Exit
    )
)||(
    mode con cols=90 lines=20
    echo( & echo     It is necessary to start the script with administrative rights.
    echo( & echo     Please wait ... I am restarting the script with administrative rights.
    echo( & echo     Answer "YES" to the next User Account Control UAC request to continue
    echo(     running this script with administrative permissions. & echo(
    timeout /t 4
    powershell.exe -c "Start -WindowStyle Maximized -Verb RunAs cmd /c, ("^""%~f0"^"" -replace '[;,=() &^]', '^$0'), "admin" " & Exit
)
goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:video_setting
    For /F %%a In ('echo prompt $E^| cmd') Do Set "ESC=%%a"
    set "CSI=%ESC%[" & set "RI=%ESC%M"
    set "echoVT=<nul set/p.="
        rem get windows size
    for /f "tokens=1,2 skip=3" %%A in ('powershell -command "$Host.ui.rawui.WindowSize"'
    ) do set /a windowWidth=%%A, windowHeight=%%B, sm_e=%%B - 3
    mode con: COLS=%windowWidth% LINES=%windowHeight%
    Rem Setting Scrolling Margins
    echo %CSI%4;%sm_e%r
    rem set UTF-8
    chcp 65001
    cls
goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:pad
  set "pad=!%1!"
  for /L %%L in (1,1,%2) do set "pad= !pad!"
  set "pad=!pad:~-%2!"
  set "%1=!pad!"
goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::