Jump to content

How to remove windows store apps for current user with dism?


Recommended Posts

; www.autoitscript.com/forum/topic/179486-solved-dllcall-on-64-bit-autoit-version-not-work-properly
; autoit.de/index.php?thread/37747-tribut-an-die-community-dism-udf

#NoTrayIcon
#RequireAdmin
#include <Constants.au3>
#include <GUIConstants.au3>
#include <WinAPIsysinfoConstants.au3>
#include <WinAPISys.au3>
#include <WinAPIMisc.au3>
#include <WinAPIProc.au3>
#include <Array.au3>
#include <Misc.au3>

Opt('SendKeyDelay', 0)
Opt('MouseClickDelay', 0)
Opt('SendKeyDownDelay', 0)
Opt('MouseClickDownDelay', 0)
Opt('MouseClickDragDelay', 0)
Opt('WinTitleMatchMode', 3)
Opt('WinWaitDelay', 0)
_Singleton(@ScriptName, 0)
ProcessSetPriority(@AutoItPID, $PROCESS_ABOVENORMAL)
FileChangeDir(StringRegExpReplace(@ScriptDir, '\\+$', ''))
_WinAPI_SetThreadExecutionState(BitOR($ES_CONTINUOUS, $ES_SYSTEM_REQUIRED, $ES_DISPLAY_REQUIRED))

If not FileExists(@SystemDir & '\DismApi.dll') Then
   MsgBox($MB_OK, 'Info', 'DismApi.dll not found in ' & @SystemDir & '.')
   Exit
EndIf

Global $DesktopWorkArea = _GetDesktopWorkArea()
Global $MainGui = GUICreate('', 220, 38, $DesktopWorkArea[0] + ($DesktopWorkArea[2] - 220)/2, 0, $WS_CAPTION)
Global $CurrentActivityLabel = GUICtrlCreateLabel('', 3, 1, 214, 36, BitOR($SS_CENTER, $BS_MULTILINE))
_SetFont($CurrentActivityLabel, 'control', 11)
GUICtrlSetData($CurrentActivityLabel, 'Uninstalling all provisioned appx packages...')
GUISetState(@SW_SHOW, $MainGui)

$FuncReturn = _UninstallAllProvisionedAppxPackages()
If @extended = -1 Then
   GUISetState(@SW_HIDE, $MainGui)
   _ArrayDisplay($FuncReturn, 'Failed to uninstall apps:', '', 64)
EndIf
Exit

Func _SetFont($sTargetId, $sMode = 'control', $sFontSize = 9, $sFontName = 'Verdana', $sFontWeight = 400, $sFontAttribute = 0, $sFontQuality = 2)
   ;$sMode values: gui or control
   Switch $sMode
   Case 'gui'
      $sFuncReturn = GUISetFont($sFontSize, $sFontWeight, $sFontAttribute, $sFontName, $sTargetId, $sFontQuality)
      Return $sFuncReturn
   Case 'control'
      $sFuncReturn = GUICtrlSetFont($sTargetId, $sFontSize, $sFontWeight, $sFontAttribute, $sFontName, $sFontQuality)
      Return $sFuncReturn
   Case Else
      Return SetError(1, 0, 0)
   EndSwitch
EndFunc

Func _GetDesktopWorkArea()
   $tDesktopWorkArea = DllStructCreate($tagRECT)
   _WinAPI_SystemParametersInfo($SPI_GETWORKAREA, 0, DllStructGetPtr($tDesktopWorkArea))
   $sDesktopWidth = DllStructGetData($tDesktopWorkArea, 'Right') - DllStructGetData($tDesktopWorkArea, 'Left')
   $sDesktopHeight = DllStructGetData($tDesktopWorkArea, 'Bottom') - DllStructGetData($tDesktopWorkArea, 'Top')
   Local $sDesktopWorkArea[4] = [DllStructGetData($tDesktopWorkArea, 'Left'), DllStructGetData($tDesktopWorkArea, 'Top'), $sDesktopWidth, $sDesktopHeight]
   Return $sDesktopWorkArea
EndFunc

Func _UninstallAllProvisionedAppxPackages($sAppxPackagesToKeep = 'Microsoft.DesktopAppInstaller|Microsoft.StorePurchaseApp|Microsoft.WindowsStore')
   ;$sAppxPackagesToKeep can be appx display name or array of appx display names with | as delimiter
   ;if @extended is -1, then return value is array of failed to uninstall apps
   Local $sFailedToUninstallAppsList[1][3] = [['Display Name', 'Package Name', 'Error Code']]
   If @OSBuild < 7600 or not FileExists(@SystemDir & '\DismApi.dll') Then Return SetError(1, 0, False)
   $sDismSessionHandle = _DismOpenSessionOnline()
   If @error Then Return SetError(2, @error, False)
   $sAppxPackagesList = _DismGetProvisionedAppxPackages($sDismSessionHandle)
   If @error Then Return SetError(3, @error, False)
   $sFailedToUninstallAppsCount = 0
   For $i = 1 to UBound($sAppxPackagesList) - 1
      If not StringInStr($sAppxPackagesToKeep & '|', $sAppxPackagesList[$i][0] & '|') Then
         _DismRemoveProvisionedAppxPackage($sDismSessionHandle, $sAppxPackagesList[$i][1])
         If @error Then
            $sLastErrorCode = @error
            If @extended <> 0 Then $sLastErrorCode = Hex(@extended)
            $sFailedToUninstallAppsCount += 1
            If UBound($sFailedToUninstallAppsList) <= $sFailedToUninstallAppsCount Then ReDim $sFailedToUninstallAppsList[UBound($sFailedToUninstallAppsList)*2][3]
            $sFailedToUninstallAppsList[$sFailedToUninstallAppsCount][0] = $sAppxPackagesList[$i][0]
            $sFailedToUninstallAppsList[$sFailedToUninstallAppsCount][1] = $sAppxPackagesList[$i][1]
            $sFailedToUninstallAppsList[$sFailedToUninstallAppsCount][2] = $sLastErrorCode
         EndIf
      EndIf
   Next
   ReDim $sFailedToUninstallAppsList[$sFailedToUninstallAppsCount + 1][3]
   _DismCloseSession($sDismSessionHandle)
   If UBound($sFailedToUninstallAppsList) - 1 > 0 Then Return SetError(4, -1, $sFailedToUninstallAppsList)
   Return True
EndFunc

Func _DismOpenSessionOnline()
   $DISM_ONLINE_IMAGE = 'DISM_{53BFAE52-B167-4E2F-A258-0A37B57FF845}'
   If not IsDeclared('__DismApiDll') Then Global $__DismApiDll = DllOpen('DismApi.dll')
   If @OSBuild < 7600 or not FileExists(@SystemDir & '\DismApi.dll') Then Return SetError(1, 0, 0)
   $sDllReturn = DllCall($__DismApiDll, 'long', 'DismInitialize', 'int', 0, 'ptr', 0, 'ptr', 0)
   If @error or $sDllReturn[0] <> 0 Then Return SetError(2, $sDllReturn[0], 0)
   $sDllReturn = DllCall($__DismApiDll, 'long', 'DismOpenSession', 'wstr', $DISM_ONLINE_IMAGE, 'ptr', 0, 'ptr', 0, 'ptr*', 0)
   If @error or $sDllReturn[0] <> 0 Then Return SetError(3, $sDllReturn[0], 0)
   If $sDllReturn[4] = 0 Then Return SetError(4, 0, 0)
   Return $sDllReturn[4]
EndFunc

Func _DismCloseSession($sDismSessionHandle)
   If not IsDeclared('__DismApiDll') Then Global $__DismApiDll = DllOpen('DismApi.dll')
   If @OSBuild < 7600 or not FileExists(@SystemDir & '\DismApi.dll') Then Return SetError(1, 0, False)
   $sDllReturn = DllCall($__DismApiDll, 'long', 'DismCloseSession', 'ptr', $sDismSessionHandle)
   If @error or $sDllReturn[0] <> 0 Then Return SetError(2, $sDllReturn[0], False)
   $sDllReturn = DllCall($__DismApiDll, 'long', 'DismShutdown')
   If @error or $sDllReturn[0] <> 0 Then Return SetError(3, $sDllReturn[0], False)
   Return True
EndFunc

Func _DismRemoveProvisionedAppxPackage($sDismSessionHandle, $sAppxPackageName)
   If not IsDeclared('__DismApiDll') Then Global $__DismApiDll = DllOpen('DismApi.dll')
   If @OSBuild < 7600 or not FileExists(@SystemDir & '\DismApi.dll') Then Return SetError(1, 0, False)
   $sDllReturn = DllCall($__DismApiDll, 'long', '_DismRemoveProvisionedAppxPackage', 'ptr', $sDismSessionHandle, 'wstr', $sAppxPackageName, 'int', 0, 'ptr', 0, 'ptr', 0, 'ptr', 0)
   If @error or $sDllReturn[0] <> 0 Then Return SetError(2, $sDllReturn[0], False)
   Return True
EndFunc

Func _DismDelete($sDismStructPtr)
   If not IsDeclared('__DismApiDll') Then Global $__DismApiDll = DllOpen('DismApi.dll')
   If @OSBuild < 7600 or not FileExists(@SystemDir & '\DismApi.dll') Then Return SetError(1, 0, False)
   $sDllReturn = DllCall($__DismApiDll, 'long', 'DismDelete', 'ptr', $sDismStructPtr)
   If @error or $sDllReturn[0] <> 0 Then Return SetError(2, $sDllReturn[0], False)
   Return True
EndFunc

Func _DismGetProvisionedAppxPackages($sDismSessionHandle)
   If not IsDeclared('__DismApiDll') Then Global $__DismApiDll = DllOpen('DismApi.dll')
   If @OSBuild < 7600 or not FileExists(@SystemDir & '\DismApi.dll') Then Return SetError(1, 0, '')
   $sDllReturn = DllCall($__DismApiDll, 'long', '_DismGetProvisionedAppxPackages', 'ptr', $sDismSessionHandle, 'ptr*', 0, 'uint*', 0)
   If @error or $sDllReturn[0] <> 0 Then Return SetError(2, $sDllReturn[0], '')
   $sAppxPackagesCount = $sDllReturn[3]
   $sDismAppxPackagesInfoPtr = $sDllReturn[2]
   If $sAppxPackagesCount = 0 Then Return SetError(3, 0, '')
   $sDismAppxPackageInfo = ''
   For $i = 1 to $sAppxPackagesCount
      $sDismAppxPackageInfo = $sDismAppxPackageInfo & 'align 4;ptr pPackageName;ptr pDisplayName;ptr pPackageId;dword iMajorVersion;dword iMinorVersion;dword iBuildVersion;dword iRevisionVersion;dword iArchitecture;ptr pResourceId;ptr pManifestPath;'
   Next
   $tDismAppxPackagesInfo = DllStructCreate($sDismAppxPackageInfo, $sDismAppxPackagesInfoPtr)
   Local $sAppxPackagesList[$sAppxPackagesCount + 1][2] = [['Display Name', 'Package Name']]
   $sElement = 0
   For $i = 1 to $sAppxPackagesCount
      $sAppxPackagesList[$i][0] = _WinAPI_GetString(DllStructGetData($tDismAppxPackagesInfo, $sElement + 2))
      $sAppxPackagesList[$i][1] = _WinAPI_GetString(DllStructGetData($tDismAppxPackagesInfo, $sElement + 1))
      $sElement += 10
   Next
   _DismDelete($sDismAppxPackagesInfoPtr)
   Return $sAppxPackagesList
EndFunc

What should be changed in _DismRemoveProvisionedAppxPackage function so that windows store apps get removed from current user?

 

 

 

Link to comment
Share on other sites

For some reason Dism doesn't always show the full list of features (in my experience anyway), but found powershell was always correct, I use the following as part of an SCCM Task Sequence to remove the features, I use both Remove-AppxPackage and Remove-AppxProvisionedPackage as below for Windows 10 new installs/upgrades.
nb: This is a cut down version of what I use, by default I use ini file with the feature name and the action and just loop through and afterwards print out the result to a log file.

;~ Removes from Existing User Profile
Run(@ComSpec & ' /c PowerShell.exe -Command "& {Get-AppxPackage *Microsoft.BingWeather* | Remove-AppxPackage}"')

;~ Removes from New User Profiles
Run(@ComSpec & ' /c PowerShell.exe -Command "& {Get-AppxProvisionedPackage -Online | Where-Object {$_.PackageName -like ' & "'*Microsoft.BingWeather*'" & '} | Remove-AppxProvisionedPackage -Online}"')

 

Edited by Subz
Link to comment
Share on other sites

are you saying there are scenarios where this list is incomplete and the PS is not?

dism /online /Get-ProvisionedAppxPackages

 

 

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

@iamtheky Unsure if the question is directed at me, but if so no, what I mean is Get-AppxPackage and Get-AppxProvisionedPackage can return different lists, as mentioned above one is for current user and the other for new users, when removing I also found that the full names can be slightly different which is why I use wild cards (see above):

Get-AppxProvisionedPackage for 3DBuilder
Microsoft.3DBuilder_16.1.1431.0_neutral_~_8wekyb3d8bbwe

Get-AppxPackage for 3DBuilder
Microsoft.3DBuilder_16.1.1431.0_x64__8wekyb3d8bbwe

 

Link to comment
Share on other sites

it was for you, just sanity checking.  Now I have to go pick one and make sure Im not using those interchangably.

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...