RemoteApp and Desktop Connections

by | Last updated 2022.10.29 | Published on 2020.05.25 | Guides

How Do I Add RemoteApp Connections?

Ever get sick of trying to find the right way of mass-adding a RemoteApp connection feed to a large amount of computers? There are a few ways: manually (YUCK!), and automatically using a GPO:

User Configuration > Policies > Administrative Templates > Windows Components > Remote Desktop Services > RemoteApp and Desktop Connections > Specify a default connection URL

GPO Policy of Specify default connection URLBut using a GPO has some issues. First, you can only specify ONE default connection. What if you have multiple RemoteApp environments to deploy? An example would be a Live Environment and a Test Environment. What if you also needed a 3rd environment for an Upgrade Environment that will eventually become your Live Environment, just on new major versions of various software. How do you mass deploy your feeds to your client systems?

Another method is to use a PowerShell script. The current way which has been the most popular is the Install-RADCConnection.ps1 file that you can download from the TechNet Gallery. This will install a connection using a WCX file that RemoteApp uses, however this script has not been updated in a long time, and while it works, there are some errors that I was receiving when trying to use this script.

How Do I Remove RemoteApp Connections?

I also have not found a method to REMOVE these connections without manually visiting each computer (YUCK!). Why oh why does it have to be this difficult? (Hint: it no longer has to be this difficult!)

After some research, I decided it was time to make a function to do both of these tasks, both adding and removing. Language of choice: PowerShell!

I’ve decided to re-write this cmdlet and create it so that it does not produce errors and works with Windows 7 (we should all be off Windows 7 by now anyways – it’s past the EOL) and higher (we should all be on a supported version of Windows 10) . Copy and paste the following code into Notepad and save the file as “Add-RADCConnection.ps1” or “Remove-RADCConnection.ps1” respectively.

Add-RADCConnection:

<#
.SYNOPSIS
Adds a connection in RemoteApp and Desktop Connections.

.DESCRIPTION
This cmdlet uses a RemoteApp and Desktop Connections bootstrap file (a .wcx file) to set up a connection in Windows 7 and later systems without user interaction.
This cmdlet is perfect for adding multiple RADC connections to a user's profile. It sets up a connection only for the current user and you must always run the script in the user's session.
The necessary credentials must be available either as domain credentials or as cached credentials on the local machine. (You can use Cmdkey.exe to cache the credentials.)
Error status information is saved in event log: (Applications and Services\Microsoft\Windows\RemoteApp and Desktop Connections).

.NOTES
Name: Add-RADCConnection
By: AJ Tek
Copyright: AJ Tek Corporation 2020. All Rights Reserved.
License: Free to use for corporate and personal use.

.PARAMETER WCXPath
Specifies the path to the .wcx file

.EXAMPLE
Add-RADCConnection -WCXPath .\server.domain.local.wcx
Description: Adds a RemoteApp and Desktop Connection using a wcx file in the same folder.

.EXAMPLE
Add-RADCConnection -WCXPath "\\server.doman.local\share\Work Resources.wcx"
Description: Adds a RemoteApp and Desktop Connection using a UNC Path to the wcx file.

.LINK
https://www.ajtek.ca
#>
[CmdletBinding()]
Param(
    [parameter(Mandatory=$true,Position=0)]
    [string]$WCXPath
)
Begin {
    [xml]$WCXXML = [string]::Join("", (Get-Content -LiteralPath $(Get-Item $WCXPath).FullName))
}
Process {
    function Test-RADCConnection {
        Param (
            [parameter(Mandatory=$true,Position=0)]
            [string]$URL
            )
        Get-ChildItem HKCU:\Software\Microsoft\Workspaces\Feeds\ | ForEach-Object {
            Try {
                $ErrorActionPreference = "Stop"
                if (((Get-ItemProperty -Path $_.PSPath).URL -eq $URL)) {
                    Write-Verbose "URL found in $_"
                    # Copyright: AJ Tek Corporation 2020. All Rights Reserved.
                    Throw "The connection in RemoteApp and Desktop Connections already exists."
                }
            }
            Catch {
                Throw "$_"
            }
        }
    }
    if ([string]::isnullorempty($WCXXML.workspace.defaultFeed.url)) {
        Throw "WCX file does not contain the proper syntax. Are you sure this is a Remote Desktop Connection File?"
    } else {
        Test-RADCConnection $WCXXML.workspace.defaultFeed.url
    }

    Try {
        $ErrorActionPreference = "Stop"
        # Copyright: AJ Tek Corporation 2020. All Rights Reserved.
        Start-Process -FilePath rundll32.exe -ArgumentList 'tsworkspace,WorkspaceSilentSetup',$(Get-Item $WCXPath).FullName -NoNewWindow -Wait 
    }
    Catch {
        Throw @"
     
        Connection setup failed.

        $_.Exception
 
        Consult the event log for failure information: 
        (Applications and Services\Microsoft\Windows\RemoteApp and Desktop Connections). 
"@
    }
    Write-Output "Connection setup succeeded."
}
End {

}

# Copyright: AJ Tek Corporation 2020. All Rights Reserved.

Remove-RADCConnection:

<#
.SYNOPSIS
Removes a connection in RemoteApp and Desktop Connections.

.DESCRIPTION
This script will remove a workspace in RemoteApp and Desktop Connections without user interaction.
It only removes a connection for the current user. Always run the script in the user's session context.

.NOTES
Name: Remove-RADCConnection
By: AJ Tek
Copyright: AJ Tek Corporation 2020. All Rights Reserved.
License: Free to use for corporate and personal use.

.PARAMETER WorkspaceID
Specifies the WorkspaceID of the RemoteApp Connection. This is usually the FQDN of the server or an alias FQDN.

.PARAMETER URL
Specifies the URL of the RemoteApp Connection's webfeed. This is the full URL to the webfeed.aspx file.

.EXAMPLE
Remove-RADCConnection -WorkspaceID server02.domain.local
Description: Removes a RemoteApp and Desktop Connection with the WorkspaceID of server02.domain.local.

.EXAMPLE
Remove-RADCConnection -URL https://server02.domain.local/RDWeb/Feed/webfeed.aspx
Description: Removes a RemoteApp and Desktop Connection with the URL of https://server02.domain.local/RDWeb/Feed/webfeed.aspx.

.LINK
https://www.ajtek.ca/
#>
[CmdletBinding()]
Param (
    [string]$WorkspaceID, # Specify the WorkspaceID - the FQDN of the URL.
    [string]$URL # Specify the full URL of the connection you wish to remove.
)
Begin {
    if ([string]::isnullorempty($WorkspaceID) -and [string]::isnullorempty($URL)) { Throw "You must specify either a WorkspaceID or URL to remove." }
    if (![string]::isnullorempty($WorkspaceID) -and ![string]::isnullorempty($URL)) { Throw "You must specify either a WorkspaceID or URL to remove, you can't supply both." }
}
Process {
    Get-ChildItem HKCU:\Software\Microsoft\Workspaces\Feeds\ | ForEach-Object {
        if (((Get-ItemProperty -Path $_.PSPath).WorkspaceID -eq $WorkspaceID) -or ((Get-ItemProperty -Path $_.PSPath).URL -eq $URL)) {
            Write-Verbose "WorkspaceID or URL found in $_"
            # Copyright: AJ Tek Corporation 2020. All Rights Reserved.
            Get-ItemProperty -Path $_.PSPath | Select-Object * | Format-List | Out-String | Write-Verbose
            Write-Output "Found $((Get-ItemProperty -Path $_.PSPath).WorkspaceID)."
            Write-Output "Removing from the workspace folder."
            Get-ChildItem -Path $(Get-ItemProperty -Path $_.PSPath).WorkSpaceFolder -Recurse | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
            Remove-Item $(Get-ItemProperty -Path $_.PSPath).WorkSpaceFolder -ErrorAction SilentlyContinue
            # Copyright: AJ Tek Corporation 2020. All Rights Reserved.
            Write-Output "Removing from the Windows menu."
            Get-ChildItem -Path (Get-ItemProperty -Path $_.PSPath).StartMenuRoot | Remove-Item -Recurse -ErrorAction SilentlyContinue
            Remove-Item $(Get-ItemProperty -Path $_.PSPath).StartMenuRoot -ErrorAction SilentlyContinue
            Write-Output "Removing from the registry."
            # Copyright: AJ Tek Corporation 2020. All Rights Reserved.
            Get-Item -Path $_.PSPath | Remove-Item -Recurse -ErrorAction SilentlyContinue
        }
        else { Write-Verbose "WorkspaceID or URL not found in $_" }
    }
}

# Copyright: AJ Tek Corporation 2020. All Rights Reserved.

Sample WCX File. Simply save it as “server.domain.local.wcx” or whatever you want as long as it has a .wcx extension. Modify the defaultFeed line to adjust it to your RDS server name or alias name as a FQDN.

Sample WCX File (server.domain.local.wcx):

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<workspace name="Company Applications" xmlns="http://schemas.microsoft.com/ts/2008/09/tswcx" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <defaultFeed url="https://server.domain.local/RDWeb/Feed/webfeed.aspx" />
</workspace>

Since most people who are starting PowerShell end up using cmdlet files, I’ve built these functions as files, but they can easily be wrapped into a function call for advanced users within their own scripts. Simply add

function Add-RADCConnection {
    [cmdlet from above]
}

or

function Remove-RADCConnection {
    [cmdlet from above]
}

Then you can simply call Add-RADCConnection and Remove-RADCConnection from within your own scripts.

How To Fix WSUS Synchronization Errors

How To Fix WSUS Synchronization Errors

Sometimes WSUS has issues synchronizing with the upstream server – usually Microsoft, but it can be a local upstream server. Why these errors happen can be for many reasons.Microsoft requires several websites to be accessible through the firewall to synchronize. These...

How to Prepare for On-Prem WSUS UUP Updates

How to Prepare for On-Prem WSUS UUP Updates

Quality updates are coming on March 28 for on-premises Windows 11, version 22H2 devices. The updates are coming via the Unified Update Platform (UUP) which interoperates with WSUS and Microsoft Configuration Manager. UUP quality updates are cumulative, including all...