Remove Builtin Apps from Windows 10 reference image

Windows 10 includes a list of universal apps (running on Windows Runtime, or WinRT introduced in Windows 8). And some of them are great for the home user.


However, some of them you might not want around in your corporate image. Either because the doesn’t make sense to keep around your end users (e.g. “Contact Service” which gets them in touch with Microsoft Support or “Mail” when you already use Outlook in your corporation), or simply because you want a more business oriented image.

The universal apps are installed on a per user basis, which means that the first time you log on to a computer, the apps will be installed in your profile. Ever wondered why the first logon on Windows 10 takes a long time with the “Hi , We’re Setting Things Up For You”? It’s because it is installing the apps in the user profile. If you would like to get an example of how much you can optimize this, go to the bottom of this page.

If you want to get a complete list of all the apps installed in your profile, you can run the PowerShell script:

Get-AppXPackage | Select Name

Get-AppXPackage returns the list of app packages (.appx) that is installed for the current user. In addition, you can run Get-AppXPackage -AllUsers in an elevated PowerShell prompt, to get the netto list of packages installed for all users (but since everyone gets everything installed, this list would probably be equal to the list for your profile, unless you already have uninstalled some of the apps).

On my test-computer this would produce the following list:


A universal app, which gets installed the first time you log on, is called a provisioned app package (.appx). To get the list of all provisioned app packages available on your system, type in the following PowerShell in an elevated 64-bit console:

Get-AppXProvisionedPackage -Online | Select DisplayName

You must use the parameter -Online to specify that it should look in the online running Windows image. If you’ve mounted a WIM file to a folder, you could use -Path instead. By the way, DISM /Online /Get-ProvisionedAppxPackages would give the same list as the -Online parameter.

The list of provisioned app packages is:

Notice that this must be run from a 64-bit PowerShell console. If you run it from a 32-bit console, you will get the error “An attempt was made to load a program with an incorrect format”:


This list of provisioned app packages is significantly smaller than the list of all universal apps installed on your profile. As it turns out, not all apps, which is installed on the first logon, can be uninstalled.

Uninstalling the apps

In order to uninstall an universal app, you must first uninstalled it for all users, and then you must uninstall the provisioned app package. If you plan to modify the list of apps during the creation of you reference image via MDT, this would mean that you need to uninstall the apps for the local administrator, as well as the provisioned app package.

First you uninstall the universal app for the local administrator using:

Get-AppXPackage Microsoft.BingSports | Remove-AppXPackage

And then the provisioned app package:

$App = Get-AppXProvisionedPackage -Online | Where {$_.DisplayName -eq "Microsoft.BingSports" }
Remove-AppXProvisionedPackage -Online -PackageName $App.PackageName


As mentioned, not all installed apps can be removed. If you for instance try to remove the Windows.ContactSupport app, you will be met by an error “This app is part of Windows and cannot be uninstalled on a per-user basis.”:


And if you notice, the system app Windows.ContactSupport is not listed as one of the provisioned app packages, which was returned by Get-AppXProvisionedPackage -Online


I’ve compiled a list of the provisioned app packages which can be removed, and the system apps which cannot be removed using the method described above (on a Windows 10 Enterprise):

Name System app
(Cannot be removed)
Provisioned App Package
(Can be removed)
Microsoft.3DBuilder X
Microsoft.AccountsControl X
Microsoft.Appconnector X
Microsoft.BingFinance X
Microsoft.BingNews X
Microsoft.BingSports X
Microsoft.BingWeather X
Microsoft.BioEnrollment X
Microsoft.Getstarted X
Microsoft.LockApp X
Microsoft.MicrosoftEdge X
Microsoft.MicrosoftOfficeHub X
Microsoft.MicrosoftSolitaireCollection X
Microsoft.NET.Native.Framework.1.0 X
Microsoft.NET.Native.Runtime.1.0 X
Microsoft.Office.OneNote X
Microsoft.People X
Microsoft.SkypeApp X
Microsoft.VCLibs.120.00 X
Microsoft.VCLibs.140.00 X
Microsoft.Windows.AssignedAccessLockApp X
Microsoft.Windows.CloudExperienceHost X
Microsoft.Windows.ContentDeliveryManager X
Microsoft.Windows.Cortana X
Microsoft.Windows.ParentalControls X
Microsoft.Windows.Photos X
Microsoft.Windows.ShellExperienceHost X
Microsoft.WindowsAlarms X
Microsoft.WindowsCalculator X
Microsoft.WindowsCamera X
microsoft.windowscommunicationsapps X
Microsoft.WindowsFeedback X
Microsoft.WindowsMaps X
Microsoft.WindowsPhone X
Microsoft.WindowsSoundRecorder X
Microsoft.WindowsStore X
Microsoft.XboxApp X
Microsoft.XboxGameCallableUI X
Microsoft.XboxIdentityProvider X
Microsoft.ZuneMusic X
Microsoft.ZuneVideo X
Microsoft.AAD.BrokerPlugin X
Windows.ContactSupport X
windows.immersivecontrolpanel X
Windows.MiracastView X
Windows.PrintDialog X
Windows.PurchaseDialog X

For the curious reader, when you log on the first time, the “source files” for the provisioned app packages are stored in C:\Program Files\WindowsApps, while the source for the static apps are in C:\Windows\SystemApps.


How to really remove the system apps

As it turns out, it is possible to remove the system apps, by first removing the lock Windows keeps on the system app, and then removing the app (the method described here, I got from this file). Lets say we want to remove Windows.ContactSupport:

  1. Open registry key as admin, and browse to SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages
  2. Locate the key Microsoft-Windows-ContactSupport-Package~31bf3856ad364e35~amd64~~10.0.10240.16384
  3. Give yourself Full Permission to that key and subkeys
  4. Set the value Visibility to 1
  5. Add a new DWORD value named DefVis and set the value to 2
  6. Delete the subkey Owners
  7. Run DISM.exe /Online /Remove-Package /PackageName:Microsoft-Windows-ContactSupport-Package~31bf3856ad364e35~amd64~~10.0.10240.16384
  8. Note that you need to repeat the process for the language-specific version
  9. Finally remove the package from the currently logged in user by Get-AppxPackage -Name “Windows.ContactSupport” -AllUsers | Remove-AppxPackage

Note when using this method as a part of creating a reference image: If you do not remove both the system app, and the app that is installed for the currently logged on user, you will get an error during the sysprep step (something in the lines of “…was installed for a user, but not provisioned for all users. This package will not function properly in the sysprep image“).


Putting it all together

If you’ve come this far, you would probably like one script to contain it all. So, here it is:

$ProvisionedAppPackageNames = @( 
	"microsoft.windowscommunicationsapps" #Mail, Calendar

foreach ($ProvisionedAppName in $ProvisionedAppPackageNames) {
    Get-AppxPackage -Name $ProvisionedAppName -AllUsers | Remove-AppxPackage
    Get-AppXProvisionedPackage -Online | where DisplayName -EQ $ProvisionedAppName | Remove-AppxProvisionedPackage -Online

$RootPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\"

$SystemAppNames = @( "Windows-ContactSupport" )

foreach ($SystemAppName in $SystemAppNames) {
    $RegistryKeyApps = (ls "HKLM:\$RootPath" | where Name -Like "*$SystemAppName*")
	foreach($RegistryKeyApp in $RegistryKeyApps)
		$RegistryKey = $RegistryKeyApp.Name.Substring(19) #Remove HKEY_LOCAL_MACHINE from string
		Write-Host $RegistryKey
		$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($RegistryKey,[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::ChangePermissions)
		$acl = $key.GetAccessControl()
		$rule = New-Object System.Security.AccessControl.RegistryAccessRule ("${[system.environment]::MachineName}\Administrator","FullControl","Allow")

		$subkey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("$RegistryKey\Owners",[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::ChangePermissions)
		$subacl = $subkey.GetAccessControl()
		Set-ItemProperty -Path "HKLM:\$RegistryKey" -Name Visibility -Value 1
		New-ItemProperty -Path "HKLM:\$RegistryKey" -Name DefVis -PropertyType DWord -Value 2
        	Remove-Item -Path "HKLM:\$RegistryKey\Owners"
        	$AppName = $RegistryKey.Split('\')[-1]
        	DISM /Online /Remove-Package /PackageName:$AppName
	#Remember to remove it from the currently logged in user (and rename "Windows-ContactSupport" to "Windows.ContactSupport")
        Get-AppxPackage -Name $SystemAppName.Replace("-",".") -AllUsers | Remove-AppxPackage


You can call it RemoveBuiltinAppsInWindows10.ps1.


Whats the speed difference at the first logon?

I’ve conducted a small benchmark test because I was curious. I made two Windows 10 Enterprise reference images. One with the full set of apps, and one where I’ve removed the 14 apps listed in the PowerShell script. Then I’ve compared the first logon-time for a new profile on the two images:

Average first logon-time with all apps: 2:10

Average first logon-time with a subset of the apps: 1:35

So, if you don’t want the extra apps in your corporate image, and care about user experience on the first logon, you might want to remove them extra apps.

5 thoughts on “Remove Builtin Apps from Windows 10 reference image

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s