Slimdown11 – turn Windows 11 or LTSC 2024 into classic/legacy Windows

Discussion in 'Windows 11' started by SunLion, Mar 2, 2025.

  1. sergey130270

    sergey130270 MDL Senior Member

    May 15, 2014
    350
    558
    10
    #2081 sergey130270, Aug 9, 2026
    Last edited: Aug 9, 2026
    Code:
    echo.
    echo ------------------------------------------------------------
    echo Test Remove optional Windows capabilities
    echo ------------------------------------------------------------
    echo.
    
    setlocal EnableDelayedExpansion
    
    set "RemoveCapabilities="
    
    set "UseCustomList=1"
    set "CustomList=%~dp0CustomRemovalList.txt"
    
    if "%UseCustomList%"=="1" if exist "!CustomList!" (
        echo.
        echo ------------------------------------------------------------
        echo Applying Custom Capability List...
        echo ------------------------------------------------------------
        echo.
    
        for /F "tokens=1,* delims=:" %%A in ('findstr /i /b "CAPABILITY:" "!CustomList!" 2^>nul') do (
        
            set "RemoveCapabilities=!RemoveCapabilities! %%B"
            echo [CUSTOM] %%B
        )
    )
    
    for %%P in (!RemoveCapabilities!) do (
        echo [Removing] %%P
    
       "%DISM11%" /English /Image:"%MountDir%" /Remove-Capability /CapabilityName:%%P >nul 2>&1
          
       if !errorlevel! equ 0 (
            echo [OK] %%P
        ) else (
            echo [SKIPPED] %%P
        )
    )
    
        echo.
        echo Custom Capability removal test completed.
    
        endlocal
    
     
  2. sergey130270

    sergey130270 MDL Senior Member

    May 15, 2014
    350
    558
    10
    My script uses the following code variant:
    Code:
        echo.
        echo ------------------------------------------------------------
        echo Remove optional Windows capabilities
        echo ------------------------------------------------------------
        echo.
      
    setlocal EnableDelayedExpansion
        set /a capCount=0
    
    set "RemoveCapabilities="
    
    set "RemoveCapabilities=!RemoveCapabilities! App.StepsRecorder"
    set "RemoveCapabilities=!RemoveCapabilities! Browser.InternetExplorer"
    set "RemoveCapabilities=!RemoveCapabilities! MathRecognizer"
    set "RemoveCapabilities=!RemoveCapabilities! Microsoft.Windows.PowerShell.ISE"
    set "RemoveCapabilities=!RemoveCapabilities! Print.Management.Console"
    set "RemoveCapabilities=!RemoveCapabilities! OpenSSH.Client"
    
    if /i "%RemoveWMP%"=="1" (
        set "RemoveCapabilities=!RemoveCapabilities! Media.WindowsMediaPlayer"
       )
      
    if /i "%RemoveLanguageCapabilities%"=="1" (
        set "RemoveCapabilities=!RemoveCapabilities! Language.Handwriting~~~ru-RU~0.0.1.0 Language.OCR~~~en-US~0.0.1.0 Language.OCR~~~ru-RU~0.0.1.0 Language.TextToSpeech~~~ru-RU~0.0.1.0"
    )
    
    for %%P in (!RemoveCapabilities!) do (
        echo [Removing] %%P
    
    "%DISM11%" /English /Image:"%MountDir%" /Remove-Capability /CapabilityName:%%P >nul 2>&1
    
    if !errorlevel! equ 0 (
        set /a capCount+=1
        echo [OK] %%P
        ) else (
        echo [SKIPPED] %%P (Not Installed)
       )
    )
    
        echo.
        echo Total removed capabilities: !capCount!
        echo Optional Windows capabilities cleanup completed successfully.
        endlocal
    
     
  3. otvertka

    otvertka MDL Member

    Aug 13, 2009
    109
    253
    10
    Hello @sainfo ,

    After automatically generating the UseCustomList.txt file using a PowerShell script, I called and ran it using the following code, but it failed. This is because the PowerShell script added all the capability-Appx and features in the ISO file—whether installed, not installed, or disabled—to the .txt file, which caused the script to encounter an error (error 87) while running.


    Code:
    echo.
    echo.
    if "%UseCustomList%"=="1" if exist "!CustomList!" (
        echo ============================================================
        echo Applying Custom Removal List from PackageSelector...
        echo ============================================================
        FOR /F "tokens=1,* delims=:" %%A IN ('findstr /i "APPX:" "!CustomList!" 2^>nul') DO (
            "%DISM11%" /English /quiet /Image:"%~dp0mount" /Remove-ProvisionedAppxPackage /PackageName:%%B
        )
        FOR /F "tokens=1,* delims=:" %%A IN ('findstr /i "CAPABILITY:" "!CustomList!" 2^>nul') DO (
            "%DISM11%" /English /quiet /Image:"%~dp0mount" /Remove-Capability /CapabilityName:%%B
        )
        FOR /F "tokens=1,* delims=:" %%A IN ('findstr /i "FEATURE:" "!CustomList!" 2^>nul') DO (
            "%DISM11%" /English /quiet /Image:"%~dp0mount" /Disable-Feature /FeatureName:%%B /Remove
        )
    )
    There's an error here in the usecustolist.txt file; a lot of unnecessary items are listed here. These need to be filtered out, and then this code will work without any issues.
     
  4. otvertka

    otvertka MDL Member

    Aug 13, 2009
    109
    253
    10
    Hello! I found the source of the problem: The DISM output for `Get-Capabilities` and `Get-Features` includes the `State` information for each package/feature (Installed/Not Present, Enabled/Disabled), but the script currently only retrieves the names and doesn’t check the `State` at all. That’s why when trying to remove or disable a capability that isn’t already installed or a feature that’s already disabled, DISM returns error 87 (invalid parameter).
    With the fix I made:
    CAPABILITY list: It now checks the “State:” line for each block in the Get-Capabilities output. Only those with State = Installed are added to the table; those marked as “Not Present” are not listed at all.
    FEATURE list: Same logic—features in the Get-Features output that do not have State = Enabled (e.g., Disabled, Disabled with Payload Removed, etc.) are not included in the list.
    APPX list: No changes, because there is no “not installed” state for provisioned APPX packages—they are all already provisioned to the image.
    As a side effect, since only items that can actually be removed or disabled will now be written to the UseCustomList.txt file, the DISM commands in your batch file should run without returning Error 87. I haven’t tested this yet, but I’ll try it as soon as possible.
     

    Attached Files:

  5. otvertka

    otvertka MDL Member

    Aug 13, 2009
    109
    253
    10
    From now on, you should only list the names of APPX, CAPABILITY, and FEATURE files that can actually be removed or disabled in UseCustomList.txt; you shouldn't get Error 87 from DISM.
     

    Attached Files:

  6. sainfo

    sainfo MDL Addicted

    Dec 6, 2021
    707
    1,590
    30
    That part is perfectly clear. But your comment was about something else—the Capabilities_State.txt and Features_State.txt files. I was very curious to see how you implemented the processing of these files in your version of the code.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  7. otvertka

    otvertka MDL Member

    Aug 13, 2009
    109
    253
    10
    sainfo, I mounted an ISO file and generated a list of all the capability-feature and Appx files in that ISO. (I did this to view them.) Then, using the .ps1 file I created, I transferred the applications or features that could be removed (whichever were appropriate) from these lists to the usecustomlist.txt file, and I ran the script using the code I shared above within that file.
    I transferred the list using the following code:

    Code:
    rd /s/q "%~dp0mount" >NUL 2>&1
    rd /s/q "%~dp0temp" >NUL 2>&1
    mkdir "%~dp0mount" >NUL 2>&1
    mkdir "%~dp0temp" >NUL 2>&1
    set MT=mount
    ECHO.
    ECHO.
    echo ============================================================
    ECHO Mounting image with index 1
    ECHO Mount directory: %~dp0mount
    "%DISM%" /English /Get-WimInfo /WimFile:"%~dp0DVD\sources\install.wim" /Index:1 | find /i "Name :"
    ECHO ============================================================
    ECHO.
    "%DISM11%" /English /Mount-Wim /WimFile:"%~dp0DVD\sources\install.wim" /index:1 /MountDir:"%~dp0mount"
    PAUSE
    
    ECHO.
    ECHO.
    echo ============================================================
    ECHO Generating Capabilities and Features report (State included)
    ECHO ============================================================
    "%DISM11%" /English /Image:"%~dp0mount" /Get-Capabilities > "%~dp0Capabilities_Report.txt"
    "%DISM11%" /English /Image:"%~dp0mount" /Get-Features > "%~dp0Features_Report.txt"
    findstr /C:"Capability Identity" /C:"State" "%~dp0Capabilities_Report.txt" > "%~dp0Capabilities_State.txt"
    findstr /C:"Feature Name" /C:"State" "%~dp0Features_Report.txt" > "%~dp0Features_State.txt"
    ECHO.
    ECHO Reports saved:
    ECHO   %~dp0Capabilities_State.txt
    ECHO   %~dp0Features_State.txt
    ECHO ============================================================
    PAUSE
    and the most recent .ps1 file produced good results:
    CAPABILITY: Only those with State = Installed can be selected from the list. Those with State = Staged are also displayed but are grayed out, labeled “Staged (Not Installed - Cannot Be Uninstalled),” and their checkboxes are unclickable.
    FEATURE: Only those with State = Enabled appear in the list (those with State = Disabled or DisabledWithPayloadRemoved do not appear at all).
    The “Locked” mechanism now works as intended: For all entries—CRITICAL (System), Menu Protected, CRITICAL (Language Pack), and the newly added Staged entries—the checkbox is now physically disabled (gray background + faded text), so you cannot accidentally click and select them.
     
  8. sergey130270

    sergey130270 MDL Senior Member

    May 15, 2014
    350
    558
    10
    #2088 sergey130270, Aug 10, 2026
    Last edited: Aug 10, 2026
    Test Version-Custom Removal List
    This test allows FEATURE: and CAPABILITY: entries to be maintained in one external CustomRemovalList.txt file.
    The important point for this test is the processing order:
    1. FEATURES are loaded and removed first.
    2. CAPABILITIES are loaded and removed afterwards.
    This version has been tested successfully with Windows 11 24H2 / image version 26100.1742.

    Code:
    echo.
    echo ------------------------------------------------------------
    echo  Test Custom Removal List
    echo ------------------------------------------------------------
    echo.
    
    setlocal EnableDelayedExpansion
    
    set "RemoveCapabilities="
    set "RemoveFeatures="
    
    set "UseCustomList=1"
    set "CustomList=%~dp0CustomRemovalList.txt"
    
    if "%UseCustomList%"=="1" if exist "!CustomList!" (
    
        echo.
        echo ------------------------------------------------------------
        echo Applying Custom Removal List...
        echo ------------------------------------------------------------
        echo.
     
        for /F "tokens=1,* delims=:" %%A in ('findstr /i /b "FEATURE:" "!CustomList!" 2^>nul') do (  
            set "RemoveFeatures=!RemoveFeatures! %%B"
            echo [CUSTOM FEATURE] %%B
        )
    
        for /F "tokens=1,* delims=:" %%A in ( 'findstr /i /b "CAPABILITY:" "!CustomList!" 2^>nul') do (  
            set "RemoveCapabilities=!RemoveCapabilities! %%B"
            echo [CUSTOM CAPABILITY] %%B
        )
    )
    
    for %%F in (!RemoveFeatures!) do (
        echo [Removing Feature] %%F
    
        "%DISM11%" /English /Image:"%MountDir%" /Disable-Feature /FeatureName:%%F  /Remove >nul 2>&1
    
        if !errorlevel! equ 0 (
            echo [OK] %%F
        ) else (
            echo [SKIPPED] %%F
        )
    )
    
    for %%P in (!RemoveCapabilities!) do (
    
        echo [Removing Capability] %%P
        "%DISM11%" /English /Image:"%MountDir%" /Remove-Capability /CapabilityName:%%P >nul 2>&1
    
        if !errorlevel! equ 0 (
            echo [OK] %%P
        ) else (
            echo [SKIPPED] %%P
        )
    )
    
    echo.
    echo Custom Removal List processing completed.
    endlocal
    
    CustomRemovalList.txt
    Code:
    FEATURE:SimpleTCP
    FEATURE:TIFFIFilter
    FEATURE:Microsoft-Windows-Subsystem-Linux
    FEATURE:WCF-TCP-PortSharing45
    FEATURE:Microsoft-Hyper-V-All
    FEATURE:Microsoft-Hyper-V
    FEATURE:Microsoft-Hyper-V-Tools-All
    FEATURE:Microsoft-Hyper-V-Management-PowerShell
    FEATURE:Microsoft-Hyper-V-Hypervisor
    FEATURE:Microsoft-Hyper-V-Services
    FEATURE:Microsoft-Hyper-V-Management-Clients
    FEATURE:SmbDirect
    FEATURE:MSRDC-Infrastructure
    FEATURE:DataCenterBridging
    FEATURE:Printing-XPSServices-Features
    FEATURE:TelnetClient
    FEATURE:TFTP
    FEATURE:WindowsMediaPlayer
    
    CAPABILITY:App.StepsRecorder
    CAPABILITY:Browser.InternetExplorer
    CAPABILITY:MathRecognizer
    CAPABILITY:Microsoft.Windows.PowerShell.ISE
    CAPABILITY:Print.Management.Console
    CAPABILITY:OpenSSH.Client
    CAPABILITY:Media.WindowsMediaPlayer
    CAPABILITY:Language.Handwriting~~~ru-RU~0.0.1.0
    CAPABILITY:Language.OCR~~~ru-RU~0.0.1.0
    CAPABILITY:Language.TextToSpeech~~~ru-RU~0.0.1.0
    CAPABILITY:Language.Basic~~~ru-RU~0.0.1.0
    
     
  9. sergey130270

    sergey130270 MDL Senior Member

    May 15, 2014
    350
    558
    10
    You can continue like this
    Code:
    :: --- Remove APPX packages third ---
    for %%A in (!RemoveAppx!) do (
        echo [Removing APPX] %%A
    
        "%DISM11%" /English /quiet /Image:"%MountDir%" /Remove-ProvisionedAppxPackage /PackageName:%%A >nul 2>&1
          
        if !errorlevel! equ 0 (
            echo [OK] %%A
        ) else (
            echo [SKIPPED] %%A
        )
    )
    
    CustomRemovalList.txt
    Code:
    APPX:PackageName
    APPX: ......................
    
     
  10. sainfo

    sainfo MDL Addicted

    Dec 6, 2021
    707
    1,590
    30
    #2090 sainfo, Aug 11, 2026
    Last edited: Aug 11, 2026
    Just one question: I don't quite understand - does this parameter delete all languages except Russian, or only Russian?
    Code:
    CAPABILITY:Language.Handwriting~~~ru-RU~0.0.1.0
    CAPABILITY:Language.OCR~~~ru-RU~0.0.1.0
    CAPABILITY:Language.TextToSpeech~~~ru-RU~0.0.1.0
    CAPABILITY:Language.Basic~~~ru-RU~0.0.1.0
    
    Or is this indicated purely as an example and similar lines need to be created for all languages that the user does not need?
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  11. sergey130270

    sergey130270 MDL Senior Member

    May 15, 2014
    350
    558
    10
    These language entries are only an example for a Russian image. They remove only the specified ru-RU language capabilities; the script does not automatically remove all languages.

    If a user wants to remove another language, the corresponding Language.*~~~xx-XX~0.0.1.0 entries must be added separately to CustomRemovalList.txt.

    The remaining FEATURE and non-language CAPABILITY entries are independent of the image language and can be used according to the components present in the image.

    In other words, CustomRemovalList.txt is fully customizable: users can add or remove specific FEATURE and CAPABILITY entries according to their own requirements and the contents of their Windows image.
     
  12. otvertka

    otvertka MDL Member

    Aug 13, 2009
    109
    253
    10
    update..PackageSelector.ps1


    The mechanism works as follows:

    • When PackageSelector.ps1 runs, it fetches the actual capability and feature list from the mounted image (using Get-Capabilities, Get-Features).

    • It compares each item against the contents of DATA\files\Capabilities.txt (and Features.txt).

    • If there is a matching name $\rightarrow$ it locks that row ("Already in Standard List (Locked)", highlighted in yellow, checkbox is unclickable).

    • You (or the user) cannot physically select that locked row in the GUI—it will not check even if you click on it.

    • Therefore, the CustomList.txt generated when you click "Save" cannot contain any names that are already present in Capabilities.txt or Features.txt—because they were never selectable in the first place.
     

    Attached Files:

  13. SunLion

    SunLion MDL Expert

    May 11, 2011
    1,721
    6,563
    60
    #2093 SunLion, Aug 11, 2026
    Last edited: Aug 11, 2026
    (OP)
    Hi otvertka,

    I am testing PackageSelector.ps1 and encountered a minor error. See below:

    I modified line 279:
    $form.DialogResult = [System.Windows.Forms.DataGridViewDialogResult]::OK

    For this reason:
    $form.DialogResult = [System.Windows.Forms.DialogResult]::OK

    And the error didn't appear again.
    Since I'm not a PowerShell expert, I don't know if this solves it...
     
  14. otvertka

    otvertka MDL Member

    Aug 13, 2009
    109
    253
    10
    #2094 otvertka, Aug 11, 2026
    Last edited: Aug 11, 2026
    I'll take a look

    The change you made—$form.DialogResult = [System.Windows.Forms.DialogResult]::OK—is the official and correct way to use Windows Forms. You're right.

    [System.Windows.Forms.DataGridViewDialogResult]::OK
    It is used in the DataGridView's row/column validation events; it is not intended to determine whether the form closes successfully. I made a mistake.
     
  15. SunLion

    SunLion MDL Expert

    May 11, 2011
    1,721
    6,563
    60
    OK

    So, I'll keep the modification.

    Note: I've already made the changes you suggested to the script. I'm waiting for the latest updates to be published, and then I'll release the new version. I'd like you to run some tests to make sure everything is working correctly.

    Thanks for the help!
     
  16. sergey130270

    sergey130270 MDL Senior Member

    May 15, 2014
    350
    558
    10
    Hi guys. I would also like to offer you a modified version of the module that can be controlled through the existing menu. This version allows the user to select what to remove via the existing menu, while the component names are stored in the CustomRemovalList.txt file.

    How it works:
    FEATURE: entries are read from the CustomRemovalList.txt file.
    CAPABILITY: entries are read from the CustomRemovalList.txt file.
    Windows Media Player can be controlled by the existing "Remove WMP" menu option.
    Language capabilities can be controlled by the existing "Remove Language Capabilities" menu option.

    This preserves the existing menu options while allowing easy customization of the removal list.

    Code:
        echo.
        echo ------------------------------------------------------------
        echo Custom Removal List
        echo ------------------------------------------------------------
        echo.
    
    setlocal EnableDelayedExpansion
    
    set "RemoveCapabilities="
    set "RemoveFeatures="
    
    set "UseCustomList=1"
    set "CustomList=%~dp0CustomRemovalList.txt"
    
    if "%UseCustomList%"=="1" if exist "!CustomList!" (
    
        echo.
        echo ------------------------------------------------------------
        echo Applying Custom Removal List...
        echo ------------------------------------------------------------
        echo.
    
        for /F "tokens=1,* delims=:" %%A in ('findstr /i /b "FEATURE:" "!CustomList!" 2^>nul') do (
           
            if /i "%%B"=="WindowsMediaPlayer" (
                if "%RemoveWMP%"=="1" (
                    set "RemoveFeatures=!RemoveFeatures! %%B"
                    echo [CUSTOM FEATURE] %%B
                ) else (
                    echo [SKIPPED BY MENU] %%B
                )
            ) else (
                set "RemoveFeatures=!RemoveFeatures! %%B"
                echo [CUSTOM FEATURE] %%B
            )
        )
    
        for /F "tokens=1,* delims=:" %%A in ('findstr /i /b "CAPABILITY:" "!CustomList!" 2^>nul') do (
           
            if /i "%%B"=="Media.WindowsMediaPlayer" (
                if "%RemoveWMP%"=="1" (
                    set "RemoveCapabilities=!RemoveCapabilities! %%B"
                    echo [CUSTOM CAPABILITY] %%B
                ) else (
                    echo [SKIPPED BY MENU] %%B
                )
    
            ) else if /i "!RemoveLanguageCapabilities!"=="0" (
                echo %%B | findstr /i /b "Language\." >nul 2>&1
    
                if !errorlevel! equ 0 (
                    echo [SKIPPED BY MENU] %%B
                ) else (
                    set "RemoveCapabilities=!RemoveCapabilities! %%B"
                    echo [CUSTOM CAPABILITY] %%B
                )
    
            ) else (
                set "RemoveCapabilities=!RemoveCapabilities! %%B"
                echo [CUSTOM CAPABILITY] %%B
            )
        )
    )
    
    
    for %%F in (!RemoveFeatures!) do (
        echo [Removing Feature] %%F
    
        "%DISM11%" /English /Image:"%MountDir%" /Disable-Feature /FeatureName:%%F /Remove >nul 2>&1
           
        if !errorlevel! equ 0 (
            echo [OK] %%F
        ) else (
            echo [SKIPPED] %%F
        )
    )
    
    
    for %%P in (!RemoveCapabilities!) do (
        echo [Removing Capability] %%P
    
        "%DISM11%" /English /Image:"%MountDir%" /Remove-Capability /CapabilityName:%%P >nul 2>&1
           
        if !errorlevel! equ 0 (
            echo [OK] %%P
        ) else (
            echo [SKIPPED] %%P
        )
    )
    
    
        echo.
        echo Custom Removal List processing completed.
    
        endlocal
    
    
        echo.
        echo ------------------------------------------------------------
        echo Save current Features, Capabilities and Provisioned AppxPackages
        echo ------------------------------------------------------------
        echo.
    
    if not exist "RemoveList" mkdir "RemoveList"
    
    if exist "RemoveList\*.txt" (
        del /f /q "RemoveList\*.txt" >nul 2>&1
    )
    
        echo.
        echo [1/3] Saving Features...
        "%DISM11%" /English /Image:"%MountDir%" /Get-Features /Format:Table > "RemoveList\Features.txt"
    
        echo.
        echo [2/3] Saving Capabilities...
        "%DISM11%" /English /Image:"%MountDir%" /Get-Capabilities /Format:Table > "RemoveList\Capability.txt"
    
        echo.
        echo [3/3] Saving Provisioned AppxPackages...
        "%DISM11%" /English /Image:"%MountDir%" /Get-ProvisionedAppxPackages /Format:Table > "RemoveList\ProvisionedAppxPackages.txt"
    
        echo.
        echo Current removal lists saved successfully.
    
     
  17. SunLion

    SunLion MDL Expert

    May 11, 2011
    1,721
    6,563
    60
    Thanks for the suggestion.

    I plan to run some tests to see how it works.

    For now, I have the script adjusted so that features and capabilities are disabled or removed via the script code itself, and advanced options do not interfere with this—following the new PackageSelector.ps1 script by @otvertka.
     
  18. SunLion

    SunLion MDL Expert

    May 11, 2011
    1,721
    6,563
    60
    =========================
    2xH2_Creator_17.4
    =========================
    Update to 26x00.9168


    - Added the new script "PackageSelector.ps1" by otvertka
    - Fixed the codes for use with Ventoy
    - Updated the APPX Files
    - Various minor modifications implemented

    Test with:
    - pt-br_windows_11_enterprise_ltsc_2024_x64_dvd_2bb6b75b_2.iso
    - 26100.1742.240909-0928.GE_RELEASE_SVC_REFRESH_CLIENTBUSINESS_VOL_X64FRE_PT-BR.ISO


    https://forums.mydigitallife.net/th...to-classic-legacy-windows.90039/#post-1872013

    Enjoy
     
  19. otvertka

    otvertka MDL Member

    Aug 13, 2009
    109
    253
    10
    Hello @SunLion , the PackageSelector.ps1 file does its job very well. As you can see in the image, it first scans all the files and selects the necessary ones, then lists the selectable options on the screen that opens and displays the unselectable ones as grayed out. This prevents conflicts and ensures an error-free process. That’s great—thank you so much. I’m testing it now, but I’m sure the results will be good.
     

    Attached Files:

    • ps1.png
      ps1.png
      File size:
      272.5 KB
      Views:
      22
  20. Mavericks Choice

    Mavericks Choice MDL Guru

    Aug 5, 2015
    4,405
    17,028
    150
    @SunLion Thankyou for the fast update, ran script & ended up with a very small wim of 3.19gb excellent, running on a VM right now. Thanks for updating the uwp apps too. Cheers.