Automating Remote Desktop Shortcut Creation Using PowerShell

Key Takeaways

  • Automated Shortcut Creation: The PowerShell script automates the creation of RDP shortcuts, saving time and reducing manual errors.
  • Customizable Options: It offers extensive customization, including display settings, user credentials, and gateway configurations.
  • Scalability for Large Environments: Ideal for MSPs and IT departments managing multiple remote connections.
  • Administrative Rights Requirement: Requires administrative privileges for certain operations, ensuring security.
  • Conflict Management: Includes checks for conflicting options, guiding users towards optimal configuration.
  • Security Conscious: Prioritizes secure handling of credentials and shortcut deployment.
  • Enhanced Productivity: Streamlines the process of remote desktop management, enhancing overall IT productivity.
  • Complementing Tools: Can be effectively paired with management platforms like NinjaOne for comprehensive IT solutions.

Remote Desktop Protocol (RDP) shortcuts are vital tools in the IT world, enabling seamless connectivity to remote systems. With the evolution of networked environments and the growing need for efficient remote access, the ability to quickly create and manage these shortcuts becomes essential. This script, crafted in PowerShell, offers a streamlined, customizable approach to creating RDP shortcuts, enhancing productivity for IT professionals and Managed Service Providers (MSPs). 

Background and Significance of the PowerShell Script

Traditionally, creating and managing RDP shortcuts involved manual processes, which could be time-consuming and error-prone, particularly in large-scale or dynamic IT environments. This PowerShell script addresses this challenge by automating the creation of RDP desktop shortcuts with user-defined parameters. Such automation is especially beneficial for IT teams managing multiple remote connections and MSPs who need to quickly deploy remote access solutions for their clients.

The Script:

<#
.SYNOPSIS
    This script will create an rdp desktop shortcut with your specified options. It can create a shortcut for all users (including new ones) or existing ones only.
.DESCRIPTION
    This script will create an rdp desktop shortcut with your specified options. 
    It can create a shortcut for all users (including new ones) or existing ones only.
.EXAMPLE
    To Create a windowed RDP Shortcut simply specify the size, the name of the shortcut and which users the shortcut is for. You can also specify "MultiMon" for multi-monitor support. Or a gateway to use.
    
    PS C:> ./Create-DesktopShortcut.ps1 -Name "Test" -RDPTarget "SRV19-TEST" -RDPUser "TESTjsmith" -Width "1920" -Height "1080" -AllExistingUsers -ExcludeUsers "ChrisWashington,JohnLocke"
    
    Creating Shortcut at C:UsersJohnSmithDesktopTest.rdp

.PARAMETER NAME
    Name of the shortcut ex. "Login Portal".

.PARAMETER RDPtarget
    IP Address or DNS Name and port to the RDS Host ex. "TEST-RDSH:28665".

.PARAMETER RDPuser
    Username to autofill in username field.

.PARAMETER AlwaysPrompt 
    Always Prompt for credentials.

.PARAMETER Gateway
    IP Address or DNS Name and port of the RD Gateway ex. "TESTrdp.example.com:4433".

.PARAMETER SeperateGateWayCreds
    If the RDS Gateway uses different creds than the Session Host use this parameter.

.PARAMETER FullScreen
    RDP Shortcut should open window in 'FullScreen' mode.

.PARAMETER MultiMon
    RDP Shortcut should open window with Multi-Monitor Support enabled.

.PARAMETER Width
    Width of RDP Window should open ex. "1920".

.PARAMETER Height
    Height of RDP Window shortcut should open ex. "1080".

.PARAMETER AllExistingUsers
    Create the Shortcut for all existing users but not new users ex. C:Users*Desktopshortcut.lnk.

.PARAMETER ExcludeUsers
    Comma seperated list of users to exclude from shortcut placement.

.PARAMETER AllUsers
    Create the Shortcut in C:UsersPublicDesktop.

.OUTPUTS
    None
.NOTES
    Minimum OS Architecture Supported: Windows 7, Windows Server 2008
    Release Notes: Renamed script, Split script into three, added Script Variable support, fixed bugs in RDP Shortcut
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#>

[CmdletBinding()]
param (
    [Parameter()]
    [String]$Name,
    [Parameter()]
    [String]$RDPtarget,
    [Parameter()]
    [String]$RDPuser,
    [Parameter()]
    [Switch]$AlwaysPrompt = [System.Convert]::ToBoolean($env:alwaysPromptForRdpCredentials),
    [Parameter()]
    [String]$Gateway,
    [Parameter()]
    [Switch]$SeparateGateWayCreds = [System.Convert]::ToBoolean($env:separateRdpGatewayCredentials),
    [Parameter()]
    [Switch]$FullScreen,
    [Parameter()]
    [Switch]$MultiMon,
    [Parameter()]
    [Int]$Width,
    [Parameter()]
    [Int]$Height,
    [Parameter()]
    [Switch]$AllExistingUsers,
    [Parameter()]
    [Switch]$AllUsers
)

begin {

    # Replace existing params with form variables if they're used.
    if ($env:shortcutName -and $env:shortcutName -notlike "null") { $Name = $env:shortcutName }
    if ($env:createTheShortcutFor -and $env:createTheShortcutFor -notlike "null") { 
        if ($env:createTheShortcutFor -eq "All Users") { $AllUsers = $True }
        if ($env:createTheShortcutFor -eq "All Existing Users") { $AllExistingUsers = $True }
    }
    if ($env:rdpServerAddress -and $env:rdpServerAddress -notlike "null") { $RDPtarget = $env:rdpServerAddress }
    if ($env:rdpUsername -and $env:rdpUsername -notlike "null") { $RDPuser = $env:rdpUsername }
    if ($env:rdpGatewayServerAddress -and $env:rdpGatewayServerAddress -notlike "null") { $Gateway = $env:rdpGatewayServerAddress }
    if ($env:rdpWindowSize -and $env:rdpWindowSize -notlike "null") {
        if ($env:rdpWindowSize -eq "Fullscreen Multiple Monitor Mode") { $MultiMon = $True }
        if ($env:rdpWindowSize -eq "Fullscreen") { $FullScreen = $True }
    }
    if ($env:customRdpWindowWidth -and $env:customRdpWindowWidth -notlike "null") { $Width = $env:customRdpWindowWidth }
    if ($env:customRdpWindowHeight -and $env:customRdpWindowHeight -notlike "null") { $Height = $env:customRdpWindowHeight }

    # Output warnings for conflicting options.
    if (($Width -and -not $Height ) -or ($Height -and -not $Width)) {
        Write-Warning "You forgot to include both the width and height. RDP Window will be in fullscreen mode."
    }

    if (($Width -or $Height) -and ($FullScreen -or $MultiMon)) {
        if ($MultiMon) {
            Write-Warning "Conflicting Display Option selected. Using Fullscreen Multi-monitor."
        }
        else {
            Write-Warning "Conflicting Display Option selected. Using Fullscreen."
        }
    }

    # Double-check that a user is specified for shortcut creation.
    if (-not $AllUsers -and -not $AllExistingUsers -and -not $User) {
        Write-Error "You must specify which desktop to create the shortcut on!"
        exit 1
    }

    # Double-check that a shortcut name was provided.
    if (-not $Name -or -not $RDPtarget) {
        Write-Error "You must specify a name and target for the shortcut!"
        exit 1
    }

    # Creating a shortcut at C:UsersPublicDesktop requires admin rights.
    function Test-IsElevated {
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $p = New-Object System.Security.Principal.WindowsPrincipal($id)
        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
    }

    if (!(Test-IsElevated)) {
        Write-Error -Message "Access Denied. Please run with Administrator privileges."
        exit 1
    }

    # Retrieve all registry paths for actual users (excluding system or network service accounts).
    function Get-UserHives {
        param (
            [Parameter()]
            [ValidateSet('AzureAD', 'DomainAndLocal', 'All')]
            [String]$Type = "All",
            [Parameter()]
            [String[]]$ExcludedUsers,
            [Parameter()]
            [switch]$IncludeDefault
        )

        # User account SIDs follow a particular pattern depending on whether they're Azure AD, Domain, or local "workgroup" accounts.
        $Patterns = switch ($Type) {
            "AzureAD" { "S-1-12-1-(d+-?){4}$" }
            "DomainAndLocal" { "S-1-5-21-(d+-?){4}$" }
            "All" { "S-1-12-1-(d+-?){4}$" ; "S-1-5-21-(d+-?){4}$" } 
        }

        # We'll need the NTuser.dat file to load each users registry hive. So we grab it if their account sid matches the above pattern. 
        $UserProfiles = Foreach ($Pattern in $Patterns) { 
            Get-ItemProperty "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionProfileList*" |
                Where-Object { $_.PSChildName -match $Pattern } | 
                Select-Object @{Name = "SID"; Expression = { $_.PSChildName } }, 
                @{Name = "UserHive"; Expression = { "$($_.ProfileImagePath)NTuser.dat" } }, 
                @{Name = "UserName"; Expression = { "$($_.ProfileImagePath | Split-Path -Leaf)" } },
                @{Name = "Path"; Expression = { $_.ProfileImagePath } }
        }

        # In some cases, it's necessary to retrieve the .Default user's information.
        switch ($IncludeDefault) {
            $True {
                $DefaultProfile = "" | Select-Object UserName, SID, UserHive, Path
                $DefaultProfile.UserName = "Default"
                $DefaultProfile.SID = "DefaultProfile"
                $DefaultProfile.Userhive = "$env:SystemDriveUsersDefaultNTUSER.DAT"
                $DefaultProfile.Path = "C:UsersDefault"

                $DefaultProfile | Where-Object { $ExcludedUsers -notcontains $_.UserName }
            }
        }

        $UserProfiles | Where-Object { $ExcludedUsers -notcontains $_.UserName }
    }
}
process {
    $ShortcutPath = New-Object System.Collections.Generic.List[String]

    # Create the filenames for the path.
    if ($RDPTarget) { $File = "$Name.rdp" }

    # Build the paths and add them to the ShortcutPath list.
    if ($AllUsers) { $ShortcutPath.Add("$env:PublicDesktop$File") }

    if ($AllExistingUsers) {
        $UserProfiles = Get-UserHives
        # Loop through each user profile
        $UserProfiles | ForEach-Object { $ShortcutPath.Add("$($_.Path)Desktop$File") }
    }

    if ($User) { 
        $UserProfile = Get-UserHives | Where-Object { $_.Username -like $User }
        $ShortcutPath.Add("$($UserProfile.Path)Desktop$File")
    }

    $RDPFile = New-Object System.Collections.Generic.List[String]

    # Base template of an .RDP file. Additional options will be appended based on user selection.
    $Template = @"
session bpp:i:32
compression:i:1
keyboardhook:i:2
audiocapturemode:i:0
videoplaybackmode:i:1
connection type:i:7
networkautodetect:i:1
bandwidthautodetect:i:1
displayconnectionbar:i:1
enableworkspacereconnect:i:0
disable wallpaper:i:0
allow font smoothing:i:0
allow desktop composition:i:0
disable full window drag:i:1
disable menu anims:i:1
disable themes:i:0
disable cursor setting:i:0
bitmapcachepersistenable:i:1
audiomode:i:0
redirectprinters:i:1
redirectcomports:i:0
redirectsmartcards:i:1
redirectwebauthn:i:1
redirectclipboard:i:1
redirectposdevices:i:0
autoreconnection enabled:i:1
authentication level:i:2
negotiate security layer:i:1
remoteapplicationmode:i:0
alternate shell:s:
shell working directory:s:
gatewaycredentialssource:i:4
gatewaybrokeringtype:i:0
use redirection server name:i:0
rdgiskdcproxy:i:0
kdcproxyname:s:
enablerdsaadauth:i:0
"@
    $RDPFile.Add($Template)

    # This will generate the actual .rdp file
    $ShortcutPath | ForEach-Object {
        $RDPFile.Add("full address:s:$RDPTarget")
        $RDPFile.Add("gatewayhostname:s:$Gateway")

        if ($Width) { $RDPFile.Add("desktopwidth:i:$Width") }
        if ($Height) { $RDPFile.Add("desktopheight:i:$Height") }
        if ($MultiMon) { $RDPFile.Add("use multimon:i:1") }else { $RDPFile.Add("use multimon:i:0") }
        if ($FullScreen -or $MultiMon -or !$Height -or !$Width) { $RDPFile.Add("screen mode id:i:2") }else { $RDPFile.Add("screen mode id:i:1") }
        if ($AlwaysPrompt) { $RDPFile.Add("prompt for credentials:i:1") }else { $RDPFile.Add("prompt for credentials:i:0") }
        if ($Gateway) { $RDPFile.Add("gatewayusagemethod:i:2") }else { $RDPFile.Add("gatewayusagemethod:i:4") }
        if ($SeparateGateWayCreds) { 
            $RDPFile.Add("promptcredentialonce:i:0")
            $RDPFile.Add("gatewayprofileusagemethod:i:1")  
        }
        else { 
            $RDPFile.Add("promptcredentialonce:i:1") 
            if ($Gateway) { $RDPFile.Add("gatewayprofileusagemethod:i:0") }
        }
            
        if ($RDPUser) { $RDPFile.Add("username:s:$RDPUser") }

        Write-Host "Creating Shortcut at $_"
        $RDPFile | Out-File $_

        if (!(Test-Path $_ -ErrorAction SilentlyContinue)) {
            Write-Error "Unable to create Shortcut at $_"
            exit 1
        }
    }

    exit 0
}end {
    
    
    
}

 

Access over 300+ scripts in the NinjaOne Dojo

Get Access

Exploring the Script: A Step-by-Step Breakdown

The script begins with a synopsis and description, providing a clear overview of its functionality. It then outlines parameters like the shortcut name, target RDP server, user credentials, display options (such as fullscreen or multi-monitor support), and the choice to create shortcuts for all or specific users.

  • Parameters Definition: The script defines various parameters allowing customization of the RDP shortcut. These include basic details like the shortcut name, RDP target, and user, as well as more advanced options like window size, multi-monitor support, and gateway configuration.
  • Environment Variables and Conflicts Check: The script checks and replaces parameters with environment variables if available. It also outputs warnings in case of conflicting options, such as specifying both fullscreen and window size.
  • Administrative Rights and User Profiles Handling: The script includes a function to check for administrative rights, necessary for creating shortcuts in certain directory paths. It also contains a function to retrieve user profiles, excluding system accounts, which is crucial for deploying shortcuts to specific user desktops.
  • Shortcut Creation Process: The script generates the .RDP file, appending user-selected options to a base template. It then iterates through the determined shortcut paths, creating the RDP file in each location.

Potential Use Cases: A Real-World Application

Imagine an MSP responsible for managing remote access for a company with multiple departments, each requiring specific RDP configurations. Using this script, the MSP can quickly generate tailored RDP shortcuts for each department, deploying them to respective user desktops efficiently and reducing manual setup time significantly.

Comparative Analysis: Script vs. Traditional Methods

Compared to manual RDP shortcut creation, this script offers significant advantages in terms of scalability, customization, and error reduction. While manual methods might suffice for individual setups, they become impractical in larger, more dynamic environments where this script can effortlessly manage complex configurations.

Frequently Asked Questions

  • Can the script handle different credentials for RDP and Gateway?
    Yes, it includes a parameter for separate gateway credentials.
  • Is it possible to exclude certain users?
    The script allows the exclusion of specified users from receiving the shortcut.
  • How does the script ensure security?
    It requires administrative privileges and carefully manages user credentials.

Implications and Security Considerations

While this script significantly streamlines RDP shortcut creation, it’s essential to consider security implications. Proper handling of credentials and ensuring that shortcuts are only deployed to authorized users are crucial aspects. Additionally, MSPs should regularly review shortcut configurations to maintain security standards.

Best Practices for Script Usage

  • Thorough Testing: Before widespread deployment, thoroughly test the script in a controlled environment.
  • Regular Updates: Keep the script updated with changes in network infrastructure.
  • Security Checks: Regularly review shortcut deployments for any security vulnerabilities.

Conclusion: Enhancing Remote Desktop Management with NinjaOne

In conclusion, this PowerShell script is a powerful tool for creating and managing RDP shortcuts, offering customization and efficiency. Tools like NinjaOne complement such scripts by providing a unified platform for managing IT operations, including remote desktop connections, thus streamlining IT management tasks and enhancing overall productivity and security in remote work scenarios.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

How to Monitor Log Files on macOS with a Custom Bash Script

How to Monitor Log Files and Detect Specific Text on Linux Using a Bash Script

How to Use PowerShell to Monitor Text Files and Trigger Alerts for IT Professionals

How to Automate Microsoft Safety Scanner Using a PowerShell Script

Comprehensive Guide to Using PowerShell for Efficient Event Log Searches

How to Use PowerShell to Detect Open and Established Ports in Windows

Watch Demo×
×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).