Posey's Tips & Tricks
Challenges With Using RemoteApp to Host Custom Applications Part 2
Running custom PowerShell scripts through RemoteApp can work effectively, but administrators may encounter several practical challenges involving script launching, execution policies, file blocking, and display scaling.
In the previous blog post in this series, I explained that I ran into some unexpected permissions issues related to SQL Server when I tried to host a custom PowerShell application on my RemoteApp server. Now that I have told you how I worked around the SQL Server issues, I want to turn my attention to PowerShell. Getting my custom PowerShell script to work properly on an RDS server proved to be relatively easy, but there were a couple of unexpected issues that I had to deal with.
The first challenge with using RemoteApp to host PowerShell scripts was figuring out how to publish the script. After all, RemoteApp can only publish executable code and it doesn't know what to do with PowerShell scripts.
My solution to this problem was to create a .CMD file that acts as a launcher for the PowerShell script. Even though RemoteApp cannot directly execute a .PS1 file, it can execute a .CMD file and the .CMD file can call the .PS1 file.
Incidentally, the folder containing the .CMD files has to be located on the C: drive in order to work properly. Additionally, you must reference the .CMD files by UNC path. As an example, instead of pointing the Publish RemoteApp Programs wizard to C:\Launchers\HelloWorld.cmd, I would need to point the wizard to \\PS-App.poseymgmt.com\c$\launchers\HelloWorld.cmd. These paths are obviously specific to my environment, but the underlying point of being required to use UNC paths remains.
As for the .CMD file's contents, at a minimum the .CMD file must call powershell.exe and point to the script file. As an example, the .CMD file might use a command like this one:
Powershell.exe -File "E:\Scripts\HelloWorld.ps1"
It's worth noting that the .CMD file is subject to whatever PowerShell execution policy is in place on the system. While you could set the system wide execution policy to Remote Signed or Unrestricted, I prefer to handle the execution policy within the .CMD file. In fact, you can tell PowerShell to ignore the execution policy for the specific script in question. The command used for doing so is:
Powershell.exe -ExecutionPolicy Bypass -File "E:\Scripts\HelloWorld.ps1"
Another issue that I encountered when setting up my PowerShell scripts was that some of the scripts that I created are made up of multiple .PS1 files. Initially, the server had no trouble launching the main script file, but had trouble locating the other .PS1 files that went along with it.
I fixed that particular problem by configuring my .CMD file to manually navigate to the folder where the script file needed to execute. I did this by adding some old DOS style commands to the file. Those commands need to be executed prior to calling powershell.exe. In my case, the commands look something like this:
@echo off
E:
CD\
CD scripts
Powershell.exe -ExecutionPolicy Bypass -File "E:\Scripts\HelloWorld.ps1"
The code above turns echo off, which prevents the individual commands from being displayed on screen. It then navigates to the E:\Scripts folder, and then calls powershell.exe and launches the script.
With the working folder issue resolved, the next issue that I ran into was that of script files being blocked. Normally this isn't a big deal, because PowerShell just asks you if you want to go ahead and run the script. As I said though, some of my scripts are made up of multiple files. In fact, my largest script consists of nearly 200 different .PS1 files. Imagine having to tell PowerShell that it is OK to execute each individual script.
The easiest way to resolve that problem is to right click on each script file and select the Properties command from the shortcut menu. When the properties sheet appears, go to the General tab and deselect the checkbox that designates the script as blocked. Click OK to complete the process. If you have a lot of files to unblock, you can use the Unblock-File cmdlet as an alternative.
The last issue that I had to deal with was the most unexpected and also the most difficult to resolve. Many of my PowerShell scripts are equipped with GUI interfaces that were created by using Windows forms. Because my main PC is equipped with a 4K display, I generally set the window resolution to something large, such as 3000 x 2000. Unfortunately however, the Windows RDP client didn't know how to display this resolution. My PowerShell script GUIs were displayed at the wrong resolution, resulting in the window exceeding the boundaries of the screen.
Given the length and complexity of some of my scripts, refactoring the script to use a different resolution was not an option. Likewise, no amount of trying to force the RDP session to use a specific resolution worked.
The solution that eventually worked involved modifying the .RDP file itself (you can open the file in Notepad). The first thing that I had to do was to delete the signature that appears at the end of the RDP file. Otherwise, if I had left the signature in place, then my modifications would have been interpreted as a corrupt file. With the signature gone, I added two lines of code to the top of the file. These lines are:
disable remote desktop scaling:i:1
smart sizing:i:0
Collectively these lines disable scaling, allowing the script's GUI to be displayed at the proper resolution.
About the Author
Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.