I’d like to add one more thing: this label name Code: IF "%Net35%"=="1" (SET "DN=Enable Net35") ELSE (SET "DN=Don't Enable Net35") should be changed to this, otherwise it becomes active in every case. Code: IF "%EnableNet35%"=="1" (SET "DN=Enable Net35") ELSE (SET "DN=Don't Enable Net35") The other sections are working great for me too, and the install.wim file is 4.70 GB. This can be reduced even further—it’s possible to get it down to 4 GB by removing Edge Defender. @SunLion, thank you very much for all your hard work.
The `UseCustomList` variable is a section that was forgotten or omitted in the script. As a result, even if you open the GUI using the C key and make selections, the `CustomRemovalList.txt` file is created, but this list is never processed, and therefore no additional packages are removed. Only the settings (1–23) in the main menu are applied. This code should be added immediately above the “Remove Provisioned AppxPackages” line. 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 ) )
I think the "UseCustomList" blog is very helpful; I’m removing the languages that will save a lot of space—it’s a great feature. I’m testing it right now, and I’m sure it will reduce the size of the install.wim file.
I need to look into this carefully, because there's code to remove appxpackage, to disable features, etc. It seems to me that something is still being duplicated when this code is used. I need to look into this more closely... Thank you for your help.
Code: This block effectively dynamically removes components from the mounted WIM based on a custom list. Сan try parsing it. 1. First, it checks whether the Custom List is enabled. if "%UseCustomList%"=="1" if "!CustomList!" exists. ( That is, the block does nothing at all if: UseCustomList is not equal to 1; the file specified in CustomList does not exist. This is good: the module can be left optional. 2. Then it reads the APPX from the list FOR /F "tokens=1,* delims=:" %%A IN ('findstr /i "APPX:" "!CustomList!" 2^>nul') DO ( "%DISM11%" /English /quiet /Image:"%~dp0mount" /Remove-ProvisionedAppxPackage /PackageName:%%B ) For example, if CustomList contains: APPX:Microsoft.XboxApp_... APPX:Microsoft.BingWeather_... APPX:Microsoft.GamingApp_... findstr finds lines with APPX:. And this one The tokens=1,* delims=: part splits the string by :: %%A = APPX %%B = Microsoft.XboxApp_... And then: DISM /Remove-ProvisionedAppxPackage That is, the Provisioned Appx is removed from the offline image. 3. CAPABILITY Then the scheme is completely similar: FOR /F "tokens=1,* delims=:" %%A IN ('findstr /i "CAPABILITY:" "!CustomList!" 2^>nul') DO ( "%DISM11%" /English /quiet /Image:"%~dp0mount" /Remove-Capability /CapabilityName:%%B ) For example: CAPABILITY:Language.Basic~~~ru-RU~0.0.1.0 will result in: DISM /Remove-Capability /CapabilityName:Language.Basic~~~ru-RU~0.0.1.0 4. FEATURE And the third type: FOR /F "tokens=1,* delims=:" %%A IN ('findstr /i "FEATURE:" "!CustomList!" 2^>nul') DO ( "%DISM11%" /English /quiet /Image:"%~dp0mount" /Disable-Feature /FeatureName:%%B /Remove ) For example: FEATURE:Internet-Explorer-Optional-amd64 will become: DISM /Disable-Feature /FeatureName:Internet-Explorer-Optional-amd64 /Remove An important point here: /Disable-Feature and /Remove mean not just disabling the Feature, but removing the component's payload from the image. And this is where the potential lies. This code, that is, logic that independently determines: Provisioned AppxPackages; Capabilities; Features; What to remove; What to keep. And this example allows you to create an external list, for example: APPX:Microsoft.XboxApp_... APPX:Microsoft.BingWeather_... CAPABILITY:Language.Basic~~~... FEATURE:printing-Foundation-Features And a single universal handler will automatically parse these three categories. That is, instead of storing huge blocks in the BAT: DISM ... /Remove-ProvisionedAppxPackage ... DISM ... /Remove-ProvisionedAppxPackage ... DISM ... /Remove-Capability ... DISM ... /Disable-Feature ... DISM ... /Disable-Feature ... ... You can potentially have one handler + external list.
What's especially interesting is that UseCustomList allows you to separate the processing logic from the removal list itself. Code: For example: APPX:Microsoft.Xbox... APPX:Microsoft.BingWeather... CAPABILITY:Language.Basic~~~de-DE~... CAPABILITY:Language.Basic~~~fr-FR~... FEATURE:Internet-Explorer-Optional-amd64 And the script itself understands: APPX: -/Remove-ProvisionedAppxPackage CAPABILITY: -/Remove-Capability FEATURE: -/Disable-Feature /Remove
I decided not to use the “usecustomlist.txt” file because the .ps1 file adds everything—whether installed or not—to the list, which was causing the script to fail. Instead, I made additions to the other capability and features files.
None of the language files are installed, but they are being added to the usecustomlist.txt file as if they were installed, and the script is throwing an error. I’ve tried many times—I even tried editing the .ps1 file—but I wasn’t successful.
I was thinking that several of these components are already removed by the script. So, there might be some redundancy in the selection for removal. But it's worth a try to see what happens, especially since it expands the range of removal options. I'll also add the code suggested by @otvertka and run some tests... @otvertka and @sergey130270: Thanks for the help!
I feel the same way. Let's proceed without the customlist.txt file and, if possible, expand the existing lists.
First, you need to look at the example and examine it in its entirety. Especially the places where: UseCustomList and CustomList are created and set are important. Because the section you showed is just the executor. You need to understand how the list is formed.
I mounted the ISO file, and all the capabilities (those that are installed) and features (those that are enabled) within it should be included in this list (usecustomlist.txt)—either by creating it manually or by editing the .ps1 file to list only the necessary ones.
Code: The first test is to remove one specific language. For example, suppose you had tr-TR installed in your list. Directly to the offline image: :: --- Test: Remove Turkish language --- "%DISM11%" /English /Image:"%~dp0mount" ^ /Remove-Capability ^ /CapabilityName:Language.Basic~~~tr-TR~0.0.1.0 If this works successfully, the next step is to automatically remove all tr-TR Capabilities: Language.Basic Language.Handwriting Language.OCR Language.Speech Language.TextToSpeech
Hello, could you please share the relevant parts of your code that select the Capabilities_State.txt and Features_State.txt files for execution?
Hi guys. Code: TEST PROPOSAL: CustomRemovalList + Existing Capability Removal DESCRIPTION ----------- The existing script already has working DISM logic for removing Windows Capabilities. This test does not replace that logic. The only change is to read CAPABILITY: entries from CustomRemovalList.txt and add them to the existing RemoveCapabilities list. TEST FILE --------- Create this file next to the main script: CustomRemovalList.txt For the first test: CAPABILITY:Language.Basic~~~tr-TR~0.0.1.0 CAPABILITY:Language.Handwriting~~~tr-TR~0.0.1.0 CAPABILITY:Language.OCR~~~tr-TR~0.0.1.0 CAPABILITY:Language.TextToSpeech~~~tr-TR~0.0.1.0 TEST CODE --------- Insert this block after RemoveCapabilities is created and before the existing "for %%P in (!RemoveCapabilities!) do (" loop. :: --- Custom Capability List --- set "UseCustomList=1" set "CustomList=%~dp0CustomRemovalList.txt" if "%UseCustomList%"=="1" if exist "!CustomList!" ( echo. echo ------------------------------------------------------------ echo Applying Custom Capability List... echo ------------------------------------------------------------ for /F "tokens=1,* delims=:" %%A in ( 'findstr /i /b "CAPABILITY:" "!CustomList!" 2^>nul' ) do ( set "RemoveCapabilities=!RemoveCapabilities! %%B" echo [CUSTOM] %%B ) ) EXISTING REMOVAL CODE --------------------- Keep the existing DISM removal loop unchanged: 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 ) ) EXPECTED RESULT --------------- The custom entries should first appear as: [CUSTOM] Language.Basic~~~tr-TR~0.0.1.0 [CUSTOM] Language.Handwriting~~~tr-TR~0.0.1.0 [CUSTOM] Language.OCR~~~tr-TR~0.0.1.0 [CUSTOM] Language.TextToSpeech~~~tr-TR~0.0.1.0 Then the existing DISM loop should process them: [Removing] Language.Basic~~~tr-TR~0.0.1.0 [OK] Language.Basic~~~tr-TR~0.0.1.0 If a Capability is not installed: [Removing] Language.OCR~~~tr-TR~0.0.1.0 [SKIPPED] Language.OCR~~~tr-TR~0.0.1.0 EXPLANATION ----------- This is only a test of the connection between CustomRemovalList.txt and the existing Capability removal mechanism. No counters, PowerShell, automatic list generation, or new DISM removal logic are used. If this works, the same approach can later be tested for APPX: and FEATURE: entries using the existing removal handlers.
Test Result: was successful. The CustomRemovalList.txt was correctly read, and the CAPABILITY: entries were successfully added to the existing RemoveCapabilities list. One important requirement was identified during testing: setlocal EnableDelayedExpansion is required for this block to work correctly. the custom Capability entries are processed correctly. The [SKIPPED] result in mine particular test is expected because the tested Windows image does not contain the selected tr-TR language Capabilities. So the test confirms that the CustomRemovalList.txt RemoveCapabilities existing DISM removal logic works correctly. The custom Capability entries are processed correctly.
This is all very interesting, of course, but also quite difficult to implement, in my opinion. I think the proposed approach using Capabilities_State.txt and Features_State.txt is more promising and simpler. The only thing is, I’ll test this approach as well if @otvertka shares the code for managing these files with us. I tried controlling them via PowerShell, but it didn't work...