Jump to content

Recommended Posts

Posted

I've seen a lot of advice (including on Microsoft articles/blogs) discussing the removal of Windows 10 apps to improve sign-in times as well as simply removing clutter (Solitaire Collection, anyone?). There are useful guides on how to build this process in to MDT and this all seems to do what it says on the tin.

 

However, I want to leave certain apps installed (for example Photos, the Windows Store). They are indeed left behind (by simply removing them from the RemoveApps.xml file), however they do not install on user's profiles or otherwise run. This seems to be down to the required dependency package "Microsoft.NET.Native.Runtime.1.4" going missing at some point during either RemoveApps or the Sysprep that follows when capturing a base image. I've done some testing and it appears that the .NET package only goes missing when one or more certain apps are removed. For example, if I only remove the Bing Weather app, then everything works as expected. However if I remove multiple apps (not the full list of the ones I want to remove, but a "safer" subset) I encounter the problem:

 

 

  • Microsoft.BingWeather
  • Microsoft.Getstarted
  • Microsoft.MicrosoftOfficeHub
  • Microsoft.MicrosoftSolitaireCollection
  • Microsoft.MicrosoftStickyNotes
  • Microsoft.Office.OneNote
  • Microsoft.OneConnect
  • Microsoft.Xbox.TCUI
  • Microsoft.XboxApp
  • Microsoft.XboxGameOverlay
  • Microsoft.XboxIdentityProvider
  • Microsoft.XboxSpeechToTextOverlay
  • Microsoft.ZuneMusic
  • Microsoft.ZuneVideo

 

Is anyone else currently removing provisioned apps (specifically in 1709)? Do you have a list of apps that are "safe" to remove without having a knock-on effect elsewhere? I have gone through various lists/recommendations for apps to remove, but they aren't necessarily correct for 1709. Could it be that Solitaire is actually a core component of the Windows kernel and removing it will leave your system unstable? (I've seen that joke referenced in the past towards CandyCrush).

Posted

Save this as removeapps.ps1

I use GPO to create a scheduled to run the 2 PS scripts from a net share on every start up, which means that if an update adds an app back in it gets removed before someone logs back in.

 

$AppsList = 
"Microsoft.MicrosoftOfficeHub", # Get Office
"Microsoft.SkypeApp", # Get Skype
"microsoft.windowscommunicationsapps", # Mail & Calendar
"Microsoft.People", # People
"Microsoft.CommsPhone", # Phone
"Microsoft.WindowsPhone", # Phone Companion
"Microsoft.XboxApp", # Xbox
"Microsoft.Messaging", # Messaging & Skype
"Microsoft.MicrosoftSolitaireCollection", # Microsoft Solitaire Collection
"Microsoft.BingWeather", #Microsoft Weather
"Microsoft.WindowsFeedbackHub", #FeedbackHub
"Microsoft.Office.OneNote", #OneNote
"Microsoft.3DBuilder", #3DBuilder
"Microsoft.WindowsMaps", # Maps
"Microsoft.WindowsAlarms", # Alarms
"Microsoft.WindowsCamera", # Camera - comment or remove this line for tablets
"Microsoft.GetStarted", # Getting Started
"Microsoft.ZuneMusic", #Zune
"Microsoft.ZuneVideo",
"Microsoft.XboxSpeechToTextOverlay", # Xbox
"Microsoft.XboxGameOverlay",
   "Microsoft.Xbox.TCUI",
   "Microsoft.XboxApp",
   "Microsoft.XboxGameOverlay",
   "Microsoft.XboxIdentityProvider", 
   "Microsoft.XboxSpeechToTextOverlay",
   "ThumbmunkeysLtd.PhototasticCollage",
"KeeperSecurityInc.Keeper",
"9E2F88E3.Twitter",
"king.com.CandyCrushSodaSaga",
   "King.com.BubbleWitch3Saga",
"Microsoft.BingNews",
   "Microsoft.BingSports",
   "Microsoft.BingFinance",
"flaregamesGmbH.RoyalRevolt2",
"Microsoft.MicrosoftStickyNotes", # Sticky Notes
   "Microsoft.OneConnect", # Paid wifi
   "CAF9E577.Plex",
   "89006A2E.AutodeskSketchBook",
   "A278AB0D.MarchofEmpires",
   "Microsoft.MinecraftUWP",
   "*Asphalt8Airborne*",
   "microsoft.onedrive",
   "microsoft.print3d",
   "microsoft.gethelp",
   "Microsoft.Microsoft3DViewer",
   "microsoft.wallet",
   "46928bounde.EclipseManager",
   "D5EA27B7.Duolingo-LearnLanguagesforFree",
   "Microsoft.NetworkSpeedTest",
   "Microsoft.Office.Sway",
   "Microsoft.MicrosoftPowerBIForWindows",
   "ActiproSoftwareLLC.562882FEEB491",
"A278AB0D.DisneyMagicKingdoms",
"A278AB0D.MarchofEmpires",	
   "WinZipComputing.WinZipUniversal",
"828B5831.HiddenCityMysteryofShadows"    

ForEach ($App in $AppsList)
{
$Packages = Get-AppxPackage | Where-Object {$_.Name -eq $App}
if ($Packages -ne $null)
{
	"Removing Appx Package: $App"

	foreach ($Package in $Packages) { Remove-AppxPackage -package $Package.PackageFullName }
}
else { "Unable to find package: $App" }

$ProvisionedPackage = Get-AppxProvisionedPackage -online | Where-Object {$_.displayName -eq $App}
if ($ProvisionedPackage -ne $null)
{
	"Removing Appx Provisioned Package: $App"
	remove-AppxProvisionedPackage -online -packagename $ProvisionedPackage.PackageName
}
else { "Unable to find provisioned package: $App" }
}

 

 

Save this as removepackages.ps1

Import-Module -DisableNameChecking \\dc1\netlogon\take-own.psm1 # Update this with the location you have placed the psm1 module

do {} until (Elevate-Privileges SeTakeOwnershipPrivilege)

$packages = @(
   "Browser" # Removes edge browser
   "ContactSupport" # Removes contact support
   "Xbox" # Removes remaining xbox information not removed by remove apps
   "Microsoft-PPIProjection-Package" # Removes miracast
   "Microsoft-Windows-Holographic-Desktop"
   #"cortana" #this removes Cortana, but also the ability to search the start menu
   
  
)

foreach ($package in $packages) {
   $pkgs = (ls "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages" |
       where Name -Like "*$package*")

   foreach ($pkg in $pkgs) {
       $pkgname = $pkg.Name.split('\')[-1]

       Takeown-Registry($pkg.Name)
       Takeown-Registry($pkg.Name + "\Owners")

       Set-ItemProperty -Path ("HKLM:" + $pkg.Name.Substring(18)) -Name Visibility -Value 1
       New-ItemProperty -Path ("HKLM:" + $pkg.Name.Substring(18)) -Name DefVis -PropertyType DWord -Value 2
       Remove-Item      -Path ("HKLM:" + $pkg.Name.Substring(18) + "\Owners")

       dism.exe /Online /Remove-Package /PackageName:$pkgname /NoRestart
   }
}

 

 

Save this as takeown.psm1

function Takeown-Registry($key) {
   # TODO does not work for all root keys yet
   switch ($key.split('\')[0]) {
       "HKEY_CLASSES_ROOT" {
           $reg = [Microsoft.Win32.Registry]::ClassesRoot
           $key = $key.substring(18)
       }
       "HKEY_CURRENT_USER" {
           $reg = [Microsoft.Win32.Registry]::CurrentUser
           $key = $key.substring(18)
       }
       "HKEY_LOCAL_MACHINE" {
           $reg = [Microsoft.Win32.Registry]::LocalMachine
           $key = $key.substring(19)
       }
   }

   # get administraor group
   $admins = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544")
   $admins = $admins.Translate([system.Security.Principal.NTAccount])

   # set owner
   $key = $reg.OpenSubKey($key, "ReadWriteSubTree", "TakeOwnership")
   $acl = $key.GetAccessControl()
   $acl.SetOwner($admins)
   $key.SetAccessControl($acl)

   # set FullControl
   $acl = $key.GetAccessControl()
   $rule = New-Object System.Security.AccessControl.RegistryAccessRule($admins, "FullControl", "Allow")
   $acl.SetAccessRule($rule)
   $key.SetAccessControl($acl)
}

function Takeown-File($path) {
   takeown.exe /A /F $path
   $acl = Get-Acl $path

   # get administraor group
   $admins = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544")
   $admins = $admins.Translate([system.Security.Principal.NTAccount])

   # add NT Authority\SYSTEM
   $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($admins, "FullControl", "None", "None", "Allow")
   $acl.AddAccessRule($rule)

   Set-Acl -Path $path -AclObject $acl
}

function Takeown-Folder($path) {
   Takeown-File $path
   foreach ($item in Get-ChildItem $path) {
       if (Test-Path $item -PathType Container) {
           Takeown-Folder $item.FullName
       } else {
           Takeown-File $item.FullName
       }
   }
}

function Elevate-Privileges {
   param($Privilege)
   $Definition = @"
   using System;
   using System.Runtime.InteropServices;
   public class AdjPriv {
       [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
           internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr rele);
       [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
           internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
       [DllImport("advapi32.dll", SetLastError = true)]
           internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
       [structLayout(LayoutKind.Sequential, Pack = 1)]
           internal struct TokPriv1Luid {
               public int Count;
               public long Luid;
               public int Attr;
           }
       internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
       internal const int TOKEN_QUERY = 0x00000008;
       internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
       public static bool EnablePrivilege(long processHandle, string privilege) {
           bool retVal;
           TokPriv1Luid tp;
           IntPtr hproc = new IntPtr(processHandle);
           IntPtr htok = IntPtr.Zero;
           retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
           tp.Count = 1;
           tp.Luid = 0;
           tp.Attr = SE_PRIVILEGE_ENABLED;
           retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
           retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
           return retVal;
       }
   }
"@
   $ProcessHandle = (Get-Process -id $pid).Handle
   $type = Add-Type $definition -PassThru
   $type[0]::EnablePrivilege($processHandle, $Privilege)
}

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



×
×
  • Create New...