There are a couple of things here that are specific to our environment, but I made this to keep the start menu clean of unneeded folders and links that the end user doesn’t need to see. Also this allows for a Staff Only (we’re in education and these are links the Students shouldn’t see) and TSA Only (only links for Techs) folder with appropriate rights set. I use the, very nice, NTFSSecurity module from https://github.com/raandree/NTFSSecurity to set permissions.
Since I can’t figure out how to paste code in here, I put it here: https://gist.github.com/macxcool/15c81f3b23ead6810d7ddb2039f8fb78
<code> #region Function Update-StartMenu Function Update-StartMenu { &lt;# .SYNOPSIS Cleans up the Start Menu by moving shortcuts and deleting unwanted shortcuts and folders. .DESCRIPTION Moves shortcuts to the root or a folder of the Menu and deletes unwanted shortcuts and leftover folders. .PARAMETER Folder The name of the Start Menu subfolder to work in Set this to $strStaffOnly if the links should be hidden to students. Set this to $strTSAOnly if the links should only be visible to TSAs .PARAMETER GoodLinks An array of shortcut names to keep and move to the Menu root. 'All' will keep all links... not useful in some contexts. .PARAMETER $KeepFolder A Switch parameter that retains the folder but keeps only the listed links. Can't be used with $OtherFolder or $MoveLinks .PARAMETER $OtherFolder A switch that creates a folder (if necessary) into which the links will be placed. Links from anywhere in the Start Menu can be used here. The script will look for them recursively. Only filenames unique in the hierarchy will work. Can't be used with $KeepFolder or $MoveLinks .PARAMETER $MoveLinks The default mode. A Switch to tell the script to Move the links rather than keeping or creating a folder for them. This switch is assumed and so does not have to be specified. .EXAMPLE Update-StartMenu -Folder 'Greenshot' -GoodLinks 'Greenshot','Readme' .EXAMPLE Update-StartMenu -Folder 'Some App' -GoodLinks 'All' .EXAMPLE Update-StartMenu -Folder 'Some Other App' -GoodLinks 'This App','App Website' -KeepFolder .EXAMPLE Update-StartMenu -Folder '_Staff-Only' -Goodlinks 'One','Two','Three' .NOTES Created by tv45057 for the TVDSB Deployment team #&gt; [CmdletBinding(DefaultParametersetName='MoveLinks')] Param ( [Parameter(Mandatory=$true,HelpMessage='Enter the name of a Start Menu subfolder.')] [ValidateNotNullorEmpty()] [string]$Folder, [Parameter(Mandatory=$true,HelpMessage='Enter a list of links to keep. &quot;All&quot; can be used to keep all links.')] [ValidateNotNullorEmpty()] [string[]]$GoodLinks, [Parameter(ParameterSetName='KeepFolder')] [switch]$KeepFolder, [Parameter(ParameterSetName='OtherFolder')] [switch]$OtherFolder, [Parameter(ParameterSetName='MoveLinks')] [switch]$MoveLinks ) # Set up a couple of useful variables $folderPath = &quot;$envCommonStartMenuPrograms\$($Folder)&quot; $staffFolder = $strStaffOnlyFolder $TSAFolder = $strTSAOnlyFolder # If we're using the Staff Only folder and it doesn't exist, create it and set the perms If ( !(Test-Path -Path $folderPath) -and ($Folder -eq $staffFolder) ) { New-Folder -Path $folderPath # Deny access to the Student group in the ACL. This should hide it Add-NTFSAccess -Path $folderPath -Account 'TVNET\Students' -AccessRights FullControl -AccessType Deny } # If we're using the TSA Only folder and it doesn't exist, create it and set the perms If ( !(Test-Path -Path $folderPath) -and ($Folder -eq $TSAFolder) ) { New-Folder -Path $folderPath # Remove inheritance from the folder Disable-NTFSAccessInheritance -Path $folderPath # Remove access from Users and Everyone and give it to TSA Group Remove-NTFSAccess -Path $folderPath -Account 'BUILTIN\Users' -AccessRights ReadAndExecute,Synchronize Remove-NTFSAccess -Path $folderPath -Account 'Everyone' -AccessRights ReadAndExecute,Synchronize Add-NTFSAccess -Path $folderPath -Account 'TVNET\TSA Group' -AccessRights FullControl } #### Using the KeepFolder Mode #### Keep certain files in an existing Folder and delete the rest. If ($KeepFolder) { # Check to see if the folder exists. This doesn't make much sense if it doesn't If (Test-Path -Path $folderPath -PathType Container) { # See if 'All' is being used and it's the only thing in GoodLinks If (($GoodLinks -contains 'All') -and ($GoodLinks.Count -eq 1)) { Write-Log -Message 'Warning: Doing nothing. This combination of parameters leaves everything as-is!' -Source ${cmdletName} } # If 'All' is not being used we can go ahead and remove anything not in GoodLinks ElseIf ($GoodLinks -notcontains 'All') { Write-Log -Message &quot;Removing unwanted links from Start Menu folder [$($Folder)]&quot; -Source $cmdletName # Get a full listing of the files in Folder Get-ChildItem -Path $folderPath -File -Recurse | ForEach-Object { # If this file's name isn't in GoodLinks then remove it. If ($GoodLinks -notcontains $_.BaseName) { Remove-File -Path $_.FullName } } } Else { Write-Log -Message 'Error: It does not make sense to use [All] with anything else.' -Source ${cmdletName} } } Else { Write-Log -Message &quot;Error: Folder [$($Folder)] does not exist.&quot; -Source $cmdletName } } #### Using the OtherFolder Mode #### Move files into another folder from anywhere in the Start Menu hierarchy. ElseIf ($OtherFolder) { # Using 'All' with OtherFolder doesn't really make sense. We aren't going to move all the start menu files If (($GoodLinks -contains 'All') -and ($GoodLinks.Count -eq 1)) { Write-Log -Message 'Error: [All] cannot be used with [OtherFolder]. You need to specify lnk names.' -Source $cmdletName } ElseIf ($GoodLinks -notcontains 'All') { # 'All' is not being used, so go ahead If ( ($Folder -ne $staffFolder) -and ($Folder -ne $TSAFolder) ) { New-Folder -Path $folderPath } # Now it's time to move all the goodlinks files into the folder ForEach ($link in $GoodLinks) { # Look recursively through the Start Menu for this filename and move it. Only names unique in the Start hierarchy will work. $fileObj = Get-ChildItem -Path &quot;$envCommonStartMenuPrograms&quot; -Include &quot;$($link).*&quot; -File -Recurse Write-Log -Message &quot;Moving [$($fileObj.Name)] into folder [$($Folder)]&quot; -Source $cmdletName Move-Item -Path $fileObj.FullName -Destination $folderPath #Write-Host &quot;[$($fileObj.FullName)] to [$($envCommonStartMenuPrograms)\$($Folder)] &quot; } } Else { Write-Log -Message 'Error: It does not make sense to use [All] with anything else.' -Source ${cmdletName} } } #### Using the MoveFiles Mode #### Move files into the root of the Start Menu. Else { If (Test-Path -Path $folderPath -PathType Container) { If (($GoodLinks -contains 'All') -and ($GoodLinks.Count -eq 1)) { Write-Log -Message 'Moving all Links into main Start Menu folder.' -Source ${cmdletName} Get-ChildItem -Path $folderPath -File -Recurse | ForEach-Object { Copy-File -Path $_.FullName -Destination $envCommonStartMenuPrograms } Remove-Folder -Path $folderPath } ElseIf ($GoodLinks -notcontains 'All') { ForEach ($link in $GoodLinks) { $filePath = (Get-ChildItem &quot;$folderPath\$($link).*&quot; -File -Recurse).FullName Copy-File -Path $filePath -Destination $envCommonStartMenuPrograms } Remove-Folder -Path $folderPath } Else { Write-Log -Message 'Error: It does not make sense to use [All] with anything else.' -Source ${cmdletName} } } Else { Write-Log -Message &quot;Error: Folder [$($Folder)] does not exist. Cannot complete moving of links.&quot; } } } #endregion </code>