Public/New-specStartMenuShortcut.ps1

function New-specStartMenuShortcut {
    <#
    .SYNOPSIS
        Creates a new Start Menu shortcut.
 
    .DESCRIPTION
        This function creates a shortcut in the Start Menu with the specified properties. You can run it multiple times and it will overwrite the existing shortcut.
 
    .PARAMETER ShortcutName
        The name of the shortcut (excluding the .lnk extension).
 
    .PARAMETER TargetPath
        The target path that the shortcut points to.
 
    .PARAMETER WorkingDirectory
        The working directory for the shortcut.
 
    .PARAMETER Arguments
        The command-line arguments for the target application.
 
    .PARAMETER IconLocation
        The icon for the shortcut in the format 'filename.dll,iconIndex'.
 
    .PARAMETER WindowStyle
        The window style for the shortcut (1 - Normal, 3 - Maximized, 7 - Minimized).
 
    .PARAMETER AllUsers
        Switch parameter. If present, the shortcut will be created for all users.
 
    .EXAMPLE
        New-specStartMenuShortcut -ShortcutName "MyApp" -TargetPath "C:\Path\To\MyApp.exe" -WorkingDirectory "C:\Path\To" -Arguments "-arg1 value1 -arg2 value2" -IconLocation "MyIcon.dll,0" -WindowStyle 1 -AllUsers
        Creates a Start Menu shortcut named "MyApp" with specified parameters for all users.
 
    .NOTES
        File: New-specStartMenuShortcut.ps1
        Author: owen.heaume
        1.0 - Initial function creation
        1.1 - Add support for environment variables in TargetPath
        1.2 - Fix issue with environment variables not being expanded in the shortcut object
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [string[]]$ShortcutName,

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [string]$TargetPath,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [string]$WorkingDirectory,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [string]$Arguments,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [string]$IconLocation = 'imageres.dll,4',

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [ValidateSet(1, 3, 4, 7)]
        $WindowStyle = 7,

        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [switch]$AllUsers
    )

    begin {
    }

    Process {

        foreach ($name in $ShortcutName) {
            # Expand environment variables
            $ExpandedTargetPath = $ExecutionContext.InvokeCommand.ExpandString($TargetPath)
            $ExpandedWorkingDirectory = $ExecutionContext.InvokeCommand.ExpandString($WorkingDirectory)
            $ExpandedArguments = $ExecutionContext.InvokeCommand.ExpandString($Arguments)

            # Create a WScript.Shell object
            $WshShell = New-Object -ComObject WScript.Shell

            # Determine the Start Menu path
            if ($AllUsers.IsPresent) {
                $startMenuPath = [System.IO.Path]::Combine($env:ProgramData, 'Microsoft\Windows\Start Menu\Programs')
            } else {
                $startMenuPath = [System.IO.Path]::Combine($env:APPDATA, 'Microsoft\Windows\Start Menu\Programs')
            }

            # If the icon location is not specified, use the default icon
            if ([string]::IsNullOrEmpty($IconLocation)) {
                $IconLocation = 'imageres.dll,4'
            }

            # If the WindowStyle is not specified, use 7
            if ([string]::IsNullOrEmpty($WindowStyle)) {
                $WindowStyle = 7
            }

            # Create the shortcut object
            $shortcut = $WshShell.CreateShortcut("$startMenuPath\$Name.lnk")

            try {
                # Set properties
                $shortcut.TargetPath = $expandedTargetPath
                $shortcut.Arguments = $ExpandedArguments
                $shortcut.WorkingDirectory = $ExpandedWorkingDirectory
                $shortcut.IconLocation = $IconLocation
                $shortcut.WindowStyle = $WindowStyle
                $shortcut.Save()
                Write-Host "Created shortcut: $startMenuPath\$Name.lnk" -ForegroundColor DarkGray
            } catch {
                Write-Warning $_.Exception.Message
            }
        }
    }
}