When creating your reference image for Windows 10, you might want to remove the Universal Apps for various reasons. The community have come up with several scripts to accomplish this task, and don’t want to take any credit for coming up with the idea to do it with PowerShell. However, I wanted to share my version of a PowerShell script that removed the built-in apps in Windows 10.

In this script, I’ve taken another approach compared to those created by other community members. Since new versions of Windows 10 will emerge 2-3 times a year, I don’t want to update a script to support the new version that might incorporate new Universal Apps. Instead, I’m white-listing Universal Apps that I want to keep (like the Calculator), and remove everything else. In my experience, this should lead to the least amount of maintenance and that’s what I’m all about.

Script

As with the release of Windows 10 1607, a few more apps were added compared to Windows 10 version 1511. Edit the WhiteListedApps variable and make the changes that you seem fit in terms of which apps that should not be removed. As for Features on Demand, there’s also a white list of packages that won’t be removed when running the script. Edit the WhiteListOnDemand variable to fit your organizational requirements.

Update 2017-03-23: Script updated with Write-LogEntry function to write to a log file called RemovedApps.log placed in C:\Windows\Temp. Applications like Quick Assist and Contact Support can now also be removed with this script. A bug has also been addressed causing the list of appx packages not to be fully populated.

# Functions
function Write-LogEntry {
    param(
        [parameter(Mandatory=$true, HelpMessage="Value added to the RemovedApps.log file.")]
        [ValidateNotNullOrEmpty()]
        [string]$Value,

        [parameter(Mandatory=$false, HelpMessage="Name of the log file that the entry will written to.")]
        [ValidateNotNullOrEmpty()]
        [string]$FileName = "RemovedApps.log"
    )
    # Determine log file location
    $LogFilePath = Join-Path -Path $env:windir -ChildPath "Temp\$($FileName)"

    # Add value to log file
    try {
        Add-Content -Value $Value -LiteralPath $LogFilePath -ErrorAction Stop
    }
    catch [System.Exception] {
        Write-Warning -Message "Unable to append log entry to RemovedApps.log file"
    }
}

# Get a list of all apps
Write-LogEntry -Value "Starting appx package removal"
$AppArrayList = Get-AppxPackage -PackageTypeFilter Bundle -AllUsers | Select-Object -Property Name, PackageFullName | Sort-Object -Property Name

# White list of appx packages to keep installed
$WhiteListedApps = @(
    "Microsoft.DesktopAppInstaller", 
    "Microsoft.Messaging", 
    "Microsoft.StorePurchaseApp"
    "Microsoft.WindowsCalculator", 
    "Microsoft.WindowsCommunicationsApps", 
    "Microsoft.WindowsSoundRecorder", 
    "Microsoft.WindowsStore"
)

# Loop through the list of appx packages
foreach ($App in $AppArrayList) {
    # If application name not in appx package white list, remove AppxPackage and AppxProvisioningPackage
    if (($App.Name -in $WhiteListedApps)) {
        Write-LogEntry -Value "Skipping excluded application package: $($App.Name)"
    }
    else {
        # Gather package names
        $AppPackageFullName = Get-AppxPackage -Name $App.Name | Select-Object -ExpandProperty PackageFullName
        $AppProvisioningPackageName = Get-AppxProvisionedPackage -Online | Where-Object { $_.DisplayName -like $App.Name } | Select-Object -ExpandProperty PackageName

        # Attempt to remove AppxPackage
        try {
            Write-LogEntry -Value "Removing application package: $($AppPackageFullName)"
            Remove-AppxPackage -Package $AppPackageFullName -ErrorAction Stop
        }
        catch [System.Exception] {
            Write-Warning -Message $_.Exception.Message
        }

        # Attempt to remove AppxProvisioningPackage
        if ($AppProvisioningPackageName -ne $null) {
            try {
                Write-LogEntry -Value "Removing application provisioning package: $($AppProvisioningPackageName)"
                Remove-AppxProvisionedPackage -PackageName $AppProvisioningPackageName -Online -ErrorAction Stop
            }
            catch [System.Exception] {
                Write-Warning -Message $_.Exception.Message
            }
        }
    }
}

# White list of Features On Demand V2 packages
Write-LogEntry -Value "Starting Features on Demand V2 removal"
$WhiteListOnDemand = "NetFX3|Tools.Graphics.DirectX|Tools.DeveloperMode.Core|Language"

# Get Features On Demand that should be removed
$OnDemandFeatures = Get-WindowsCapability -Online | Where-Object { $_.Name -notmatch $WhiteListOnDemand -and $_.State -like "Installed"} | Select-Object -ExpandProperty Name

foreach ($Feature in $OnDemandFeatures) {
    try {
        Write-LogEntry -Value "Removing feature on demand: $($Feature)"
        Get-WindowsCapability -Online -ErrorAction Stop | Where-Object { $_.Name -like $Feature } | Remove-WindowsCapability -Online -ErrorAction Stop
    }
    catch [System.Exception] {
        Write-Warning -Message $_.Exception.Message
    }
}

Using the script in MDT

1. Using this script is really no brainer, simply download it, call it Invoke-RemoveBuiltinApps.ps1 and place it in the %SCRIPTROOT% directory, meaning the <DeploymentShareRoot>\Scripts directory in MDT.
186_2
2. In your task sequence for Windows 10, add a Run PowerShell Script step and set the PowerShell Script field to:

%SCRIPTROOT%\Invoke-RemoveBuiltinApps.ps1

186_3_1
Start your reference image creation process and watch the magic happen!

Nickolaj Andersen
Principal Consultant and Enterprise Mobility MVP. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows deployments and Automation. In 2015 Nickolaj was awarded as PowerShell Hero by the community for his script and tools contributions. Author of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService and a frequent speaker at user groups.

(877)

comments
  • Eden Oliveira
    Posted at 21:25 March 17, 2016
    Eden Oliveira
    Reply
    Author

    Hi Nickolaj, Thank you for one more nice script.

    I have a question, I have already my Gold image built, I normally remove those apps using DISM offline, which takes some time to mount image, perform the actions, unmount, etc.
    So I was wondering, Can I use this script on my ConfigMgr 2012 Task Sequence?

    If so, how should I proceed?

    I believe I would need to create a package (no program) using this script, right?

    At which step should I add this script to on my TS?

    Thank you in advance.

    Eden

  • Dan Padgett
    Posted at 17:37 March 21, 2016
    Dan Padgett
    Reply
    Author

    just execute it as a TS step for run command line..

    %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -file .\script.ps1

    make sure you specify a source for script

  • Jo Smith
    Posted at 16:05 May 25, 2016
    Jo Smith
    Reply
    Author

    I’ve been removing “windowscommunicationsapps”. Is that really an essential app? We don’t use Calendar, Mail, or Contacts/People, so I figured it wasn’t needed. I hope it doesn’t break anything.

    • CRoth2
      Posted at 10:56 March 13, 2017
      CRoth2
      Reply
      Author

      A reply to this would be helpful. It seems “essential app” term may be a more general statement than an actual requirement. I too am not using Mail, Contacts, People, or Messaging, so I don’t see why the “microsoft.communicationsapps” would be needed. I am thinking he needed it because he was keeping Messaging.

      Explanations as to why each is “needed” or “essential” would be helpful. And clarification as to whether “essential” means to the functioning of Windows or to the apps you have selected.

  • João Torres
    Posted at 19:10 May 31, 2016
    João Torres
    Reply
    Author

    Congratulations for your amazing script, however I have a doubt. How can I remove the apps for all users? Even if it’s a new user. Because when I deployed the captured image whit your script on the TS, I logged in for the first time on the VM with the captured image but the apps still there. I tried your script on the current user and it works like a charm, but when I change user, the apps still there for the new user.

    Best Regards.

  • Anders
    Posted at 12:11 June 22, 2016
    Anders
    Reply
    Author

    Hi
    i can’t get this to work. Deployment log returns: “TSHOST: Script completed with return code 0 TaskSequencePSHost 2016-06-21 16:07:59 0 (0x0000)
    ” it does not remove any app at all. In task sequense it runs before pre win update.

  • Petr Riha
    Posted at 13:47 July 2, 2016
    Petr Riha
    Reply
    Author

    Hi & let me say THX for incredible forum at the beginning. My issue is that I tried already several options how to remove Appx from Windows 10 x64, x86 Enterprise Edt. nevertheless all new users has installed apps like CandyCrash, XBox,.. :(. Can you give me an advice where this step should be exactly situated within SCCM Task Sequence to make it working please? The same issue I am dealing with setup StartMenu modification & language settings & I hope that with some advice I will be able to solve all. Thank you in advance.

  • Steve Whitcher
    Posted at 14:45 August 10, 2016
    Steve Whitcher
    Reply
    Author

    Thanks for updating this post. Do you happen to know what the each of the new built-in apps in v1607 do?

    I’m guessing DesktopAppInstaller is for the upcoming feature allowing win32 apps to be installed from the store, which is definitely one to keep.

    I thought that Messaging is the SMS app for mobile and for text messaging on a PC when paired with a windows mobile or android device. Do I have that wrong, or is there a reason that you consider this an essential app?

    What about StorePurchaseApp, which I see that you kept, and OneConnect, which you didn’t? Any idea what either of these do?

  • Steve
    Posted at 20:20 August 10, 2016
    Steve
    Reply
    Author

    Any way to get further information for each built-in application? Looking for specifically which each application is so we can make a meaningful decision to leave in or take out of the image.

    • Nickolaj
      Posted at 08:01 August 11, 2016
      Nickolaj
      Reply
      Author

      Unfortunately, I’m not aware of any such documentation. Would also like to have that information.

  • Sam
    Posted at 22:51 October 4, 2016
    Sam
    Reply
    Author

    Does this script work offline?

    I got this to work online (during the state restore phase) but will not work during the post-install phase.

  • John
    Posted at 12:09 December 23, 2016
    John
    Reply
    Author

    Would this also work in Windows 8.1 for removing the build-in Metro apps? If no would it be possible for you to make it compatible with Windows 8.1 too?

    Would be much appreciated!

    Best regards!

  • STRiCT
    Posted at 21:43 February 10, 2017
    STRiCT
    Reply
    Author

    This script was working great for us, but after a few updates it seems to be less effective. Not sure what is going on, so I am thinking it would be handy to have some sort of log output.

    I am hoping you can either modify your script to output a log, or maybe provide some direction on doing so our selves?

  • BaardH
    Posted at 16:57 February 15, 2017
    BaardH
    Reply
    Author

    Have you experienced any problems when language packs are applied?
    Whenever i add any kind of removal script, the translation of the computers settings get’s messed up.

  • AppLearner
    Posted at 16:32 February 23, 2017
    AppLearner
    Reply
    Author

    Thank you so much for this post worked perfectly for us. Deployed this in SCCM a little different than posted.

    1. Create folder in our apps share and placed the PS script there.
    2. Create a Package, make sure you select “Do Not Create a Program”.
    3. Add a Task – “Run PowerShell Script”, Point to package, Script name, PowerShell execution Policy to “Bypass”.

    • Nickolaj
      Posted at 13:12 March 2, 2017
      Nickolaj
      Reply
      Author

      Thanks for sharing how you implemented it!

      Regards,
      Nickolaj

  • Futureshock
    Posted at 23:21 February 25, 2017
    Futureshock
    Reply
    Author

    Is this script intended to be added for the capture task sequence or for the deploy? Thanks

    • Nickolaj
      Posted at 13:11 March 2, 2017
      Nickolaj
      Reply
      Author

      You can add it where you think it fits in your environment. I’m mostly using it when capturing images.

      Regards,
      Nickolaj

      • Futureshock
        Posted at 13:44 March 2, 2017
        Futureshock
        Reply
        Author

        Ok so that’s what is confusing me. So by adding it into the capture task you are then preventing it to come again at the deploy task? Or you are actually adding it at both tasks to play safe?

        On the other hand, I have been using the script for deploy (added at the same phase level as you (so within custom tasks and before Enable Bitlocker) but it doesn’t work for me. My monitoring console does mark the deploy as 100% completed but in my test VM it stucks at the big blue screen “just wait a little bit more / configuring app”. I have to reboot it to get access to the deployed VM and when I check all built-in apps are still there.

        Any hints or ideas?
        Thank you !!

  • Andrew
    Posted at 23:13 March 17, 2017
    Andrew
    Reply
    Author

    Is this suppose to remove all Apps except the exception ones?
    I am still left with Microsoft.WindowsAlarms, Microsoft.People, Microsoft.Office.OneNote and more on 1607.

  • Leave a Reply