--- myst: html_meta: "description lang=en": "Supporting Microsoft RemoteApps on Kasm Workspaces." "keywords": "Kasm, Microsoft, Windows, RemoteApp, RDS, RDP" "property=og:locale": "en_US" --- ```{title} Windows RemoteApps ``` # Windows RemoteApps Microsoft RDP and RDS support running single applications over an RDP connection. This technology is called RemoteApp, by Microsoft. Kasm Workspaces supports Microsoft RemoteApp backed by a full [RDS infrastructure](../guide/windows/rds.md) or on stand-alone Windows systems using this open-source RemoteApp Tool, which allows you to define RemoteApps on the Windows system that can be accessed directly by Kasm as a single application. This guide covers configuring RemoteApp on individual servers without an RDS deployment. See our [RDS guide](../guide/windows/rds.md#remoteapps) for configuring Kasm Workspaces to support RemoteApp deployed via RDS. ## RemoteApp Tool This open-source [Remote App Tool](https://github.com/kimmknight/remoteapptool) allows you to define RemoteApps on a stand-alone Windows 10/11 or Windows Server operating system, without using an RDS infrastructure. 1. Download the latest release zip file [here](https://github.com/kimmknight/remoteapptool/releases) and extract it. 2. Run the `RemoteApp Tool.exe` executable. 3. Click the plus icon to add a new RemoteApp. ```{figure} /images/rds/remote_app_tool.png :align: center **Remote App Tool** ``` 4. Select the app executable to define as a remote app. In this example we are selecting PowerPoint. ```{figure} /images/rds/remote_app_powerpoint.png :align: center **Add PowerPoint** ``` 5. Click on the newly defined RemoteApp and click the Edit Properties Button. ```{figure} /images/rds/remote_app_properties.png :align: center **Select Properties** ``` 6. Copy the Name from the properties dialog, this will be used in the Kasm configuration. In this example it is `Microsoft PowerPoint`. ```{figure} /images/rds/remote_app_powerpoint_properties.png :align: center **PowerPoint Properties** ``` ## Windows Prep ```{eval-rst} In addition to using the RemoteApp tool to define the application as a RemoteApp on the Windows operating system, you should also consider installing the optional :doc:`Kasm Windows Service`, which will provide additional features such as uploads, downloads, and screenshots. ``` For a standalone Windows RemoteApp servers that are not part of an RDS deployment, you may desire to create a wrapper application rather than launching your target application directly. This will allow you to ensure the launched application is in full screen. The wrapper application can also ensure the RemoteApp is not launched again when an existing session is resumed. In addition, it would also allow you to take any custom action you desire on launch of a new session. This wrapper is not required for an RDS deployment, however, for a direct RDP RemoteApp deployment it is recommended. The following example PowerShell script does the following things. 1. Ensures there is not already an instance of this wrapper running as the same user. This ensures resumed sessions don't re-launch the target application. 2. Launches the application provided by argument 1. 3. Ensures the application being launched opens in full screen. 4. Passes the filename provided in argument 2 to the application being launched. This assumes that the application being launched will open the file provided in the first argument. This is true for many Microsoft applications, such as Excel, Word, PowerPoint, and more. 5. Monitors the target file for changes and logs the change. Add custom logic here if you need to take action on changes to the file. ```powershell $app=$args[0] $target_file=$args[1] $monitor_dir = Split-Path $target_file $monitor_file = Split-Path $target_file -Leaf $debug = $true $log_file = "C:\Users\Public\Documents\logs\log.txt" Function Write-Log { param($message) $DateFormat = "%m/%d/%Y %H:%M:%S" if ($debug -eq $true) { Write-Host ("[{0}] {1}" -F (Get-Date -UFormat $DateFormat), $message) } ("[{0}] {1}" -F (Get-Date -UFormat $DateFormat), $message) | Out-File -FilePath $log_file -Append } Function Register-Watcher { param ($folder, $filter) try { # Watch a specific file #$watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{ # Watch an entire directory, using due to issues with FileSystemWatcher with Excel, https://stackoverflow.com/questions/57036397/filesystemwatcher-only-shows-memory-adress-but-not-the-name-of-the-changed-file $watcher = New-Object IO.FileSystemWatcher $folder -Property @{ IncludeSubdirectories = $false EnableRaisingEvents = $true } # For reference: https://stackoverflow.com/questions/67824771/filewatcher-in-powershell-not-firing-events [string] $sourceId = New-Guid Register-ObjectEvent $watcher -EventName Changed -SourceIdentifier $sourceId Write-Log "Monitoring directory '$folder' for changes to '$filter'." while ($true) { $event = Wait-Event -SourceIdentifier $sourceId $event | Remove-Event $eventDetails = $event.SourceArgs[1] $changedFile = $eventDetails.FullPath Write-Log "File $changedFile has changed." # Take Custom Action Here } } finally { Write-Log 'Cleaning up...' Unregister-Event -SourceIdentifier $sourceId $watcher.Dispose() } } try { Write-Log "Launcher started with target app $app and target file $target_file." $ThisProcess = Get-Process -Id $PID $AllLaunchersInThisRDPSession = Get-Process kasm_launcher | Where-Object { $_.SessionId -eq $ThisProcess.SessionId } $FirstLauncher = $NULL $ExistingSession = $false ForEach ($Launcher in $AllLaunchersInThisRDPSession) { If ($FirstLauncher -ne $NULL) { Write-Log "Launcher already running inside session, resuming existing session." $ExistingSession = $true } else { $FirstLauncher = $Launcher } } if ($ExistingSession -eq $false) { Write-Log "Launching application at $app, with arguments $target_file " $LaunchedApp = Start-Process "$app" -WindowStyle ([System.Diagnostics.ProcessWindowStyle]::Maximized) -ArgumentList "$target_file" Register-Watcher $monitor_dir $monitor_file } } catch { Write-Log $Error[0] } ``` You can convert the PowerShell script into a standalone executable using the module `ps2exe`. Launch a PowerShell session as an administrator and run the following commands. ```powershell # Required once to initially install the module Install-Module ps2exe # Run this command each time you alter your wrapper script Invoke-ps2exe .\source.ps1 .\target.exe ``` You could then use the {doc}`Session Casting<../guide/casting>` which will allow you to share an Excel RemoteApp to users using a URL with the target spreadsheet filename as a URL parameter. This is only an example of how a Casting link could be used in conjunction with RemoteApps. ## Configuring Kasm Kasm can be configured to point to a single fixed Windows server, a pool of fixed Windows servers, or a pool of auto scaled Windows servers. We recommend watching the following Windows Guide video to get a baseline knowledge of Windows in Kasm Workspaces. ### Create a Server Pool ```{eval-rst} If you want to create a pool of identical servers that Kasm can load balance users between, first :doc:`Create a Pool<../guide/compute/pools>`. Then create each server following the guidance in the next session, selecting the pool you created when creating each server. ``` ### Create Single Fixed Server 1. In the Kasm Workspaces Admin Dashboard, expand Infrastructure and click Servers. 2. Click the Add button on the Servers list. 3. On the create server form, ensure to click enable, provide a friendly name, IP/hostname, select RDP for the connection type, provide a port number (3389 is the default for RDP). This example shows static credentials, see the video above for configuring single sign-on using active directory integration. ```{figure} /images/rds/remote_app_create_server.webp :align: center **Create Server** ``` 4. The connection info field is normally not required when specifying a Kasm Server for a full desktop, but for a RemoteApp connection we need to override what Kasm uses for the connection details so we can specify the `remote-app` name. In this example our RemoteApp name is `Microsoft PowerPoint` as determined by the steps in the RemoteApp Tool section above. Be sure to proceed the name with a double pipe, `||Microsoft PowerPoint`. The full JSON connection details are shown here. ```json { "guac": { "type": "rdp", "settings": { "security": "any", "ignore-cert": true, "enable-font-smoothing": true, "enable-wallpaper": true, "enable-theming": true, "enable-full-window-drag": false, "enable-menu-animations": false, "resize-method": "display-update", "server-layout": "en-us-qwerty", "printer-name": "Kasm", "remote-app": "||Microsoft PowerPoint" } }, "kasm_svc": { "port": 4902 } } ``` 5. Set the maximum simultaneous sessions. For Windows 10/11, this will be 1 in most cases. For Windows Server, you can license the backend server(s) to support multiple sessions. Single sign-on integration would likely be required to support multiple sessions, so that each Kasm user is mapped one-to-one to a Windows user. See the video provided above on configuring Active Directory integration. 7. If you are defining a pool of fixed servers, select the pool you created in the previous section. 6. Click Save. ### Create a Workspace In order for this Server or Server Pool to be shared with a user, you must create a Workspace definition. 1. In the Kasm Workspaces Admin Dashboard, navigate to Workspaces -> Workspaces. 2. Click the Add Workspace button in the Workspaces list. 3. On the Workspace Type drop down, select Server or Pool, depending on if you created a single Server or a Pool of Servers. 4. Provide a Friendly Name, Description, thumbnail URL, and Check the Enable box. 5. Select the desired Server or Pool. 6. Optionally provide a category for the Workspace. ```{figure} /images/rds/remote_app_workspace.webp :align: center **Create Workspace** ``` 7. Click Save. Users should now see the PowerPoint app on their dashboard. ```{figure} /images/rds/remote_app_dashboard.png :align: center **PowerPoint on Workspaces Dashboard** ``` ```{figure} /images/rds/remote_app_powerpoint_session.png :align: center **Kasm Workspaces session to a PowerPoint RemoteApp** ``` ### Developer API The above steps work great for user requested sessions through the Kasm User interface. Developers, however, may wish to launch Kasm sessions and specify the RemoteApp to launch along with RemoteApp arguments. The Kasm Workspaces [Developer API](../developers.md) allows for this. The below example shows a JSON payload using the [/api/public/request_kasm](../developers/developer_api.md#request-kasm) API. ```json { "api_key": "I8Cxl8UaeI1s", "api_key_secret": "JSEcAcYxibMKVQ1zruhsytTNlsn7OSNt", "user_id": "20df709dc4e544d5a4f6f0295e698664", "image_id": "33ee47377cb44dc184c6ed6b117d2e65", "enable_sharing": false, "connection_info": { "guac": { "type": "rdp", "settings": { "security": "any", "ignore-cert": true, "enable-font-smoothing": true, "enable-wallpaper": true, "enable-theming": true, "enable-full-window-drag": false, "enable-menu-animations": false, "resize-method": "display-update", "server-layout": "en-us-qwerty", "printer-name": "Kasm", "remote-app": "||KasmLauncher", "remote-app-args": "\"C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE\" C:\\Users\\Public\\Documents\\example.xlsx" } }, "kasm_svc": { "port": 4902 } } } ```