1

Update: I am now attempting to use a Get-StartApps command instead of recursively going through the files with a filter. Now I am in need of help re-writing the logic behind the insert sections noted in #3 below. Any suggestions would be amazing!

I found and have been working with a series of scripts that can be used to create a start menu XML. The version I have settled on is below. Unfortunately, I cannot seem to get it to handle ".URL",".Website", ".shortcut" extensions.

I have tried the following (one at a time and together):

  1. On line 90 removing the -filter "*.lnk"
  2. Adding -filter ".website", -Filter ".shortcut"... to line 90
  3. Creating ifelse statements for each of these extensions modeled after lines 107-116

      if ($SoftwareLinks.Name -like "$Software.lnk") {
        $SoftwareLink = $SoftwareLinks | where {$_ -like "$Software.lnk"} 
        $child = $StartMenuXml.CreateElement("start","DesktopApplicationTile","http://schemas.microsoft.com/Start/2014/StartLayout")
    
        if ($SoftwareLink.FullName.GetType().BaseType -eq [System.Array]) { ## If multiple links, use the first one
            $child.SetAttribute('DesktopApplicationLinkPath',$SoftwareLink.FullName[0]) 
        } else {
            $child.SetAttribute('DesktopApplicationLinkPath',$SoftwareLink.FullName) 
        }
    }
    

None of this seems to work when trying to pick up links that are placed in the start menu folder. Has anyone come across this? Do you have any advice on how to fix this? Whole script below:

        # Where to save start menu xml
#$StartMenuFile = "$ENV:programfiles\DESKTOPENGINEERING\startmenu\startmenu.xml"
$StartMenuFile = "$ENV:programfiles\DESKTOPENGINEERING\startmenu\startmenu.xml"
#$OldStartMenuFile = "$ENV:programfiles\DESKTOPENGINEERING\startmenu\startmenu.xml"
$OldStartMenuFile = "$programfiles\DESKTOPENGINEERING\startmenu\startmenu.old"


# Set this to SilentlyContinue for no debug, or Continue for debug output
$DebugPreference = "SilentlyContinue"

# Remove old startmenu.old file
IF (Test-path $OldStartMenuFile) { 
    Write-Debug "The file `"$OldStartMenuFile`" already exists and will be removed!"
    Remove-item $OldStartMenuFile -Force
} Else { 
    Write-Debug "The file `"$OldStartMenuFile`" does not exist! Lets move along then..."
}

# Rename startmenu.xml to startmenu.old
IF (Test-path $StartMenuFile) { 
    Write-Debug "renaming file `"$OldStartMenuFile`"..."
    Rename-Item -Path $StartMenuFile -NewName $OldStartMenuFile -Force
} Else { 
    Write-Debug "The file `"$OldStartMenuFile`" does not exist! Lets move along then..."
}

# One last check to see if file exists or not
IF (Test-path $StartMenuFile) { 
    Write-Error "Could not rename `"$OldStartMenuFile`", script aborted"
    Break
} Else { 
    Write-Debug "The file `"$OldStartMenuFile`" does not exist! Lets move along then..."
}

# Make sure folder exist and halt if it can't be created
$StartMenuFolder=(Split-path -parent $StartMenuFile)
IF (Test-path $StartMenuFolder) { } ELSE  { New-Item -ItemType Directory -Path $StartMenuFolder }
IF (Test-path $StartMenuFolder) { } ELSE  { Write-Error "Could not create `"$StartMenuFolder`", script aborted" ; Break }

# Specify number of cols in startmenu
$NumCol = 6
# Add the new group in $MenuGroups
# Format: "order. group title" = "list of Software Links", "Followed by other links"
$MenuGroups = @{
    "1. Internet & Network tools" = "Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge"
    "2. Microsoft Office" = "Access 2016","Excel 2016","Outlook 2016","PowerPoint 2016","Project 2016","Publisher 2016","Word 2016"
    "3. Text, file & programming tools" = "Calculator","Notepad"
    "4. Media tools" = "Paint"
    "5. Scientific software" = "Calculator"
    "6. Administrator" = "Powershell"
    "7. Other tools" = "Google Chrome", "Google Link"
}

# Building up base startmenu xml
[xml]$StartMenuXml = '<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">
  <LayoutOptions StartTileGroupsColumnCount="1" StartTileGroupCellWidth="'+$NumCol+'" />
  <DefaultLayoutOverride LayoutCustomizationRestrictionType="OnlySpecifiedGroups">
    <StartLayoutCollection>
      <defaultlayout:StartLayout GroupCellWidth="'+$NumCol+'" xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout">
      </defaultlayout:StartLayout>
    </StartLayoutCollection>
  </DefaultLayoutOverride>
  <CustomTaskbarLayoutCollection PinListPlacement="Replace">
  <defaultlayout:TaskbarLayout>
   <taskbar:TaskbarPinList>
    <taskbar:UWA AppUserModelID="Microsoft.WindowsCalculator_8wekyb3d8bbwe!App"/>
   </taskbar:TaskbarPinList>
  </defaultlayout:TaskbarLayout>
 </CustomTaskbarLayoutCollection>
</LayoutModificationTemplate>' 
# Selecting XML element where all software will be placed
$DefaultLayoutElement = $StartMenuXml.GetElementsByTagName("defaultlayout:StartLayout")
# Fetching all software links on start menu
$SoftwareLinks = Get-ChildItem "$env:PROGRAMDATA\Microsoft\Windows\Start Menu" -recurse -filter "*.lnk"
# Looping all menu groups defined above
foreach ($MenuGroup in $MenuGroups.Keys | Sort-Object) {
    # Init xml element for software group
    $SoftwareGroupXml = $StartMenuXml.CreateElement("start","Group", "http://schemas.microsoft.com/Start/2014/StartLayout")
    $SoftwareGroupXml.SetAttribute('Name',$MenuGroup.Substring(3))
    # Init row and col
    $col = 0
    $row = 0
    # Looping all software links in start menu
    foreach ($Software in $MenuGroups[$MenuGroup]) {
        # Check if it is time for a new col
        if (($col%($NumCol-1) -eq 1) -and ($col -ne 1)) {
            $row +=1
            $col = 0
        }
        # Check if specified software is found in start menu. If so, add software element
        if ($SoftwareLinks.Name -like "$Software.lnk") {
            $SoftwareLink = $SoftwareLinks | where {$_ -like "$Software.lnk"} 
            $child = $StartMenuXml.CreateElement("start","DesktopApplicationTile","http://schemas.microsoft.com/Start/2014/StartLayout")

            if ($SoftwareLink.FullName.GetType().BaseType -eq [System.Array]) { ## If multiple links, use the first one
                $child.SetAttribute('DesktopApplicationLinkPath',$SoftwareLink.FullName[0]) 
            } else {
                $child.SetAttribute('DesktopApplicationLinkPath',$SoftwareLink.FullName) 
            }
        }
        # Or check if Microsoft app is specified. If so add app element    
         elseif ($Software -like "Microsoft.*!*") {
            $child = $StartMenuXml.CreateElement("start","Tile","http://schemas.microsoft.com/Start/2014/StartLayout")
            $child.SetAttribute('AppUserModelID',$Software)
        }
        # Add common attributes is software or app is found and append xml element
        if (($child.HasAttributes) -and (($Software -like "Microsoft.*!*") -or ($SoftwareLinks.Name -like "$Software.lnk"))) {
            $child.SetAttribute('Size','2x2')
            $child.SetAttribute('Column',$col)
            $child.SetAttribute('Row',$row)
            $SoftwareGroupXml.AppendChild($child) | Out-Null
            $col +=1
        }
    }
    # If a software group is not null, add it!
    if ($SoftwareGroupXml.HasChildNodes) {
        $DefaultLayoutElement.AppendChild($SoftwareGroupXml) | Out-Null
    }
}

# Save to file
$StartMenuXml.Save($StartMenuFile)### Script ends ###
Powershelling
  • 133
  • 1
  • 6
  • 127 lines of code is not just what I'd call a [mcve]. –  Apr 25 '18 at 19:00
  • Thank you for your feedback. But for the script to make sense I needed to include all of it. The last question I asked (since deleted) I was provided feedback asking me to include the whole script. As a result I did this time. I will work to shorten it in the future. Thank you again. – Powershelling Apr 25 '18 at 19:20
  • I really wish that I could get some input on this... – Powershelling Apr 30 '18 at 12:20

1 Answers1

1

Ok so there was a two part fix. Instead of recursively searching the folders I used the built in $SoftwareLinks = Get-StartApps which solved my first problem and then re-wrote the insert string to match the new format. Thank you everyone for your feedback.

Powershelling
  • 133
  • 1
  • 6