Posted in : Microsoft, Other, System Center, Windows Server By Johan Nilsson Translate with Google ⟶

5 years ago

As I have been working with customizing Windows 10 for a while now, it has never worked against me this much. However, sometimes Windows do have its ways of working against you. With challenges like these you get the opportunity to spend a lot of time coming up with a solution. So this blog post is about my battle with the start menu of Windows 10 Professional. If you are here for the quick solution, skip to the bottom and the TL;DR section.

The Problem:

I have been able to customize the start menu of Windows 10 with ease since version 1511 with the Export / Import-StartLayout cmdlet. But this time I got a request to remove all the pinned apps on the right side of the start menu. A colleague discussed this and he told me he had done a similar solution inside a Citrix Virtual Desktop, and he spent quite the amount of time with this, I thought this would be much easier than it turned out to be. So the requested start menu should at the end look something like this upcoming picture, with the following demands:

  • No pinned apps on the right box or the start menu
  • In the task bar, have Chrome & Explorer pinned. 

This was the requested layout


To begin with, I created an XML file with just Chrome & Explorer pinned in the task bar, and having set the <DefaultLayoutOverride LayoutCustomizationRestrictionType=”OnlySpecifiedGroups”> . My thought was that this would give me a clean start menu, but this was my first failed attempt. The colleague of mine who preciously had a similar issue in a Citrix environment had during his research time come across this post containing a script called ”Pin-Apps”. This script contained a Unpin function which turned out to be very helpful. So I started adapting my work after this script. But this is where I came across my second setback. First, I was not able to have this script and the Import-StartLayout-script in the same logon script, nor having one script on startup, and one on login, so I had to think of a way configure this in my isolated lab environment.
Luckily, I’ve been working a lot with OS-deployment, so I created a Task Sequence containing the Import-StartLayout-script, which managed to run successfully together with my login-script containing the Pin-Apps script. But here I came across my third setback, which by far had the most impact and was the one I spent the most time struggling with. For some reason I was not able to remove bloatware, such as Candy Crush, Minecraft etc. The script ran successfully, but every time, the outcome looked like this

Some applications would not be removed


I could not understand why these applications would not be removed. I have had to deal with bloat ware before, but then it was just to remove them with Appx-cmdlets. I checked Get-AppxPackage & Get-AppxProvisionedPackage, and ran Remove-AppxPackage and Remove-AppxProvisionedPackage several times, but these apps were not removable and did not show up until I manually selected them, and they started downloading (as shown on the application in the top right corner on the picture). So apparently they were either links or shortcuts to the Windows Store. This is works if you are using Windows 10 Enterprise. 
This is where I started going deep. The apps were all published in the Windows AppStore, so I started looking for any kind of possibilities, with help from Powershell, to by force download all apps in the Windows Store. I spent a lot of time with this, but without any success. So I had to rethink my plan. There was no way to have the bloat ware-applications to be downloaded by force, there was no way to remove them by removing them with Appx-cmdlets, and there was no way to have a clean start menu with a XML-file. This gave me the idea. If you can’t beat them, join them. There was no way to actively remove all the applications from the start menu of a Windows 10 Professional, but replacing them worked.
The solution:
As I have yet to find any other way of removing the superfluous applications, creating a new XML replacing the start menu with some random default applications was the only successful way for me. To list these applications, go to Shell:AppsFolder or shell:::{4234d49b-0245-)4df3-b780-3893943456e1} in file explorer.

Applications can be found here


I just chose to pin some of the applications which were default on my start menu, that I knew was very much removable, exported these to a new XML which turned out to it look like this:

<?xml version="1.0" encoding="utf-8"?>
<LayoutModificationTemplate
    xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification"
    xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout"
    xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout"
    xmlns:taskbar="http://schemas.microsoft.com/Start/2014/TaskbarLayout"
    Version="1">
  <DefaultLayoutOverride LayoutCustomizationRestrictionType="OnlySpecifiedGroups">
<StartLayoutCollection>
      <defaultlayout:StartLayout GroupCellWidth="6">
        <start:Group Name="">
          <start:DesktopApplicationTile Size="2x2" Column="0" Row="2" DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\Administrative Tools\ODBC Data Sources (64-bit).lnk" />
          <start:DesktopApplicationTile Size="2x2" Column="4" Row="0" DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\Administrative Tools\Disk Cleanup.lnk" />
          <start:DesktopApplicationTile Size="2x2" Column="0" Row="0" DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\Google Chrome.lnk" />
          <start:DesktopApplicationTile Size="2x2" Column="2" Row="2" DesktopApplicationLinkPath="%APPDATA%\Microsoft\Windows\Start Menu\Programs\Windows PowerShell\Windows PowerShell.lnk" />
          <start:DesktopApplicationTile Size="2x2" Column="2" Row="0" DesktopApplicationLinkPath="%APPDATA%\Microsoft\Windows\Start Menu\Programs\Accessories\Notepad.lnk" />
        </start:Group>
      </defaultlayout:StartLayout>
    </StartLayoutCollection>
  </DefaultLayoutOverride>
  <CustomTaskbarLayoutCollection PinListPlacement="Replace">
    <defaultlayout:TaskbarLayout>
      <taskbar:TaskbarPinList>
	   <taskbar:DesktopApp DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\Outlook.lnk" />
	   <taskbar:DesktopApp DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\Google Chrome.lnk" />
	   <taskbar:DesktopApp DesktopApplicationLinkPath="%APPDATA%\Microsoft\Windows\Start Menu\Programs\System Tools\File Explorer.lnk" />
      </taskbar:TaskbarPinList>
    </defaultlayout:TaskbarLayout>
 </CustomTaskbarLayoutCollection>
</LayoutModificationTemplate>

From here I had to modify the Pin-Apps script to make it more suitable for a Swedish operating system, and added a register key so it would not run more than once on each user. If you want to lock down the right side of the start menu, you just set or create the LockedStartLayout registry key, located under both HKEY_Local_Machine & HKEY_Current_User\Software\Policies\Microsoft\Windows\Explorer, to 1

<#
.Synopsis
    Short description
.DESCRIPTION
    Detailed description
.NOTES
    Name: Unpin-Programs.ps1
    Author: Måns Hurtigh & Johan Nilsson
    Date Created: 2018-11-12
    Version History:
        2018-11-12 - Johan Nilsson & Måns Hurtigh
            Initial Creation
        2018-11-22 - Johan Nilsson
            Recreated from a verb-noun function & modified the parameters making it more GPO-friendly
    Xenit AB
#>
[cmdletbinding()]
Param(
    [string]$appname,
    [switch]$unpinAll,
    [switch]$unpin
)
begin {
    [string]$StartMenuRegName = "StartMenuReg"
    [string]$StartMenuRegType = "DWord"
    [int]$StartMenuRegValue = 1
    [string]$StartMenuRegKey = "HKCU:\Xenit"
}
Process{
    if (($false -eq (Get-ItemProperty HKCU:\Xenit\ -Name StartMenuReg).StartMenuReg -ne 1)) {
        try{
            if ($unpin.IsPresent){
                ((New-Object -Com Shell.Application).NameSpace('shell:::{4234d49b-0245-4df3-b780-3893943456e1}').Items() | Where-Object {$_.Name -eq $appname}).Verbs() | Where-Object {$_.Name.replace('&','') -match 'Ta bort från Start|Unpin from Start'} | ForEach-Object {$_.DoIt()}
                return "App '$appname' unpinned from Start"
            }
            if ($unpinAll.IsPresent -and ($false -eq (Test-Path $StartMenuRegKey))) {
                $PinApps = (New-Object -Com Shell.Application).NameSpace('shell:::{4234d49b-0245-4df3-b780-3893943456e1}').Items()
                foreach ($App in $PinApps) {
                    $app.Verbs() | Where-Object {$_.Name.replace('&','') -match 'Ta bort från Start|Unpin from Start'} | ForEach-Object {$_.DoIt()}
                }
            }
            else{
                ((New-Object -Com Shell.Application).NameSpace('shell:::{4234d49b-0245-4df3-b780-3893943456e1}').Items() | Where-Object {$_.Name -eq $appname}).Verbs() | Where-Object {$_.Name.replace('&','') -match 'Fäst på Start|Pin to Start'} | ForEach-Object {$_.DoIt()}
                return "App '$appname' pinned to Start"
            }
        }
        catch{
            Write-Error "Error Pinning/Unpinning App! (App-Name correct?)"
        }
    }
}
End{
    if (($false -eq (Get-ItemProperty HKCU:\Xenit\ -Name StartMenuReg).StartMenuReg -ne 1)){
        New-Item -Path $StartMenuRegKey -ItemType Directory
        New-ItemProperty -Path $StartMenuRegKey -Name $StartMenuRegName -Type $StartMenuRegType -Value $StartMenuRegValue
        Write-Output 'Successfully ran script - Will not run again.'
    }
    else {
        Write-Output 'Registry Keys exist - Script did not run - Exiting.'
    }
}

If you are running another OS language than Swedish or English, to find the verb for unpin, simply save an application name to the variable $appname (as an example I will use Windows Powershell) and run the following part: 

$appname = 'Windows Powershell'
((New-Object -Com Shell.Application).NameSpace('shell:::{4234d49b-0245-4df3-b780-3893943456e1}').Items() | Where-Object {$_.Name -eq $appname}).Verbs()

This will give you all the verbs which are applied to this application. In this case ”Unpin from Start” is present.
After modifying the necessary bits I added it to a PowerShell logon script GPO with the parameter -UnpinAll, with the .ps1 file located inside the GPO repository, making sure it’s accessible for everyone.

 
TL;DR: 
If you are running Windows 10 Professional, you need to replace applications in the start menu before removing them, as a suggestion running in a Task Sequence of some kind setting the default start menu layout and then have a GPO to run the PowerShell script stated above.
If you are running Windows 10 Enterprise, just use the Logon script GPO and you will be fine. If you still have some unwanted applications, run a script removing built-in apps (for example this Invoke-RemoveBuiltinApps )
If you have any questions or thoughts about this post, feel free to email me at johan.nilsson@xenit.se

Tags : Applications, Export-StartLayout, Import-StartLayout, PowerShell, Start menu, Startmeny, Unpin Applications, Windows 10, Windows 10 Professional, Windows Powershell

Personlig rådgivning

Vi erbjuder personlig rådgivning med författaren för 1400 SEK per timme. Anmäl ditt intresse i här så återkommer vi så snart vi kan.

Add comment

Your comment will be revised by the site if needed.