Setting up a PowerShell Universal development environment
August 27, 2020
Note: Consider installing the PowerShell Universal VS Code extension as it takes care of a lot of the items described in this post without any configuration required.
PowerShell Universal is the ultimate platform for building web-based solutions with PowerShell. In this post, we’ll look at how to setup a development environment for Universal. We’ll be configuring Visual Studio Code to make it easier to develop Universal scripts.
Installation
The first step in getting your environment ready is installing Universal. We offer a ton of different options for getting started on your platform.
The script below will download the 1.3.1 ZIP and extract it to the ProgramData
directory on Windows.
$Version = '1.3.1'
$Url = "https://imsreleases.blob.core.windows.net/universal/production/$Version/Universal.win-x64.$Version.zip"
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri $Url -outfile "$Env:Temp\universal.zip" -verbose
Expand-Archive "$Env:Temp\universal.zip" -DestinationPath "$Env:ProgramData\Universal"
Now that the files have been downloaded and extracted, you can start the Universal server. It will be listening on port 5000 by default.
Start-Process "$Env:ProgramData\Universal\Universal.Server.exe"
You can view the administrative console by visit http://localhost:5000
in your web browser.
Start-Process "http://localhost:5000"
You’ll be able to login to the console with the user name admin
and any password.
Scripting
You can use the Universal PowerShell module to script the basic setup of Universal rather than using the admin console. You can either install the module from the PowerShell Gallery or load it directly from the Universal installation folder.
Install-Module Universal -Scope CurrentUser -Force
Or
Import-Module "$Env:ProgramData\Universal\Cmdlets\Universal.psd1"
Once the module is installed, you’ll need to get an app token generated to interact with the server. The app token signing key is set in the appsettings.json
file within the Universal installation folder. You should change this in your production environment but we will use the default values to create an app token manually.
You can navigate to Settings / Security / AppTokens and click Grant followed by Copy to retrieve a new app token.
Once you have the app token, you can use the Connect-PSUServer
command to connect to your server.
Connect-UAServer -ComputerName http://localhost:5000 -AppToken 'eyJhbGc...'
Once you are connected, you can start to issue commands against Universal. For example, you can get all the settings from the server using Get-UASettings
.
PS C:\Users\adamr> Get-UASetting
Id : 1
LoggingFilePath :
LogLevel : Error
DefaultPowerShellVersion :
RepositoryPath : C:\ProgramData\UniversalAutomation\Repository
DatabasePath : C:\ProgramData\UniversalAutomation\database.db
GroomDays : 30
ConcurrentJobLimit : 1000
Telemetry : True
HideApi : False
HideAutomation : False
HideDashboard : False
DisableAutoReload : False
SecurityPowerShellVersion :
Visual Studio Code
Now that we have a server running and the basics of scripting setup, we can start to setup our VS Code environment.
By default, the PowerShell scripts for Universal are stored in $Env:ProgramData\UniversalAutomation\Repository
. If you open VS Code in that directory, you will see the various configuration files for Universal.
code $Env:ProgramData\UniversalAutomation\Repository
The files in this directory dictate the configuration of Universal. Changes made to the file will be automatically reloaded by Universal.
For example, you wanted to add a dashboard, you could add a new call to New-PSUDashboard
in the dashboard.ps1
file.
New-PSUDashboard -Name "Dashboard" -FilePath "Dashboard.ps1" -BaseUrl "/dashboard" -Framework "UniversalDashboard:3.0.1"
IntelliSense
One important feature of VS Code is the ability to use IntelliSense. To enable IntelliSense for Universal and Universal Dashboard commands, you’ll need to import the modules. You can do so by running the following commands.
function Import-UniversalModules {
param($AppToken, $Dashboard)
Import-Module "$Env:ProgramData\Universal\Cmdlets\Universal.psd1" -Scope Global
Connect-UAServer -ComputerName http://localhost:5000 -AppToken $AppToken
$PSUDashboard = Get-PSUDashboard | Where-Object Name -eq $Dashboard
Import-Module "$($PSUDashboard.DashboardFramework.Path)\*.psd1" -Scope Global
}
You can now import the modules used by the dashboard by using the Import-UniversalModules
function.
Registering an Editor Command
The PowerShell VS Code extension provides a Register-EditorCommand
function to allow modules to provide editor commands that run in PowerShell that have been invoked from VS Code. We can register a command to import the modules for us.
Register-EditorCommand -Name 'Import Universal Modules' -DisplayName 'Import Universal Modules' -Function {
Import-UniversalModules -AppToken $Env:AppToken -Dashboard Dashboard
}
Once that has been registered, open the command palette with Ctrl+Shift+P
and search for the PowerShell: Show additional commands from PowerShell Modules
. Once you select this, you will see your command
Controlling the state of Dashboard in VS Code
We can also control the state of a dashboard in VS Code. Sometimes it may be necessary to stop and start the dashboard.
function Restart-Dashboard {
param($Dashboard)
Get-PSUDashboard | Where-Object Name -eq $Dashboard | Stop-UDDashboard
Get-PSUDashboard | Where-Object Name -eq $Dashboard | Start-UDDashboard
}
Similar to the IntelliSense command, we can then register it with VS Code.
Register-EditorCommand -Name 'Restart Dashboard' -DisplayName 'Restart Dashboard' -Function {
Restart-Dashboard -Dashboard Dashboard
}
Setting up a VS Code profile
Like any PowerShell host, VS Code provides a profile. You can edit or create your profile by running this in the VS Code Integrated Terminal.
code $Profile
This profile script is run each time at startup. One thing that we can do to ensure that our functions and commands are registered is to create a workspace profile. VS Code doesn’t support this directly but we can use this workaround.
In my profile script, I have this code.
$WorkspaceProfile = Resolve-Path .\profile.ps1
if (Test-Path $WorkspaceProfile)
{
. $WorkspaceProfile
}
In the Universal repository folder, I’ve created a profile.ps1
file that that creates the functions and registers the commands.
function Import-UniversalModules {
param($AppToken, $Dashboard)
Import-Module "$Env:ProgramData\Universal\Cmdlets\Universal.psd1" -Scope Global
Connect-UAServer -ComputerName http://localhost:5000 -AppToken $AppToken
$PSUDashboard = Get-PSUDashboard | Where-Object Name -eq $Dashboard
Import-Module "$($PSUDashboard.DashboardFramework.Path)\*.psd1" -Scope Global
}
Register-EditorCommand -Name 'Import Universal Modules' -DisplayName 'Import Universal Modules' -Function {
Import-UniversalModules -AppToken $Env:AppToken -Dashboard Dashboard
}
function Restart-Dashboard {
param($Dashboard)
Get-PSUDashboard | Where-Object Name -eq $Dashboard | Stop-UDDashboard
Get-PSUDashboard | Where-Object Name -eq $Dashboard | Start-UDDashboard
}
Register-EditorCommand -Name 'Restart Dashboard' -DisplayName 'Restart Dashboard' -Function {
Restart-Dashboard -Dashboard Dashboard
}
With this in place, every time I open the repository folder, it will add the two commands to the VS Code command palette. This will allow me to easily load the PowerShell modules for IntelliSense and restart dashboards.
Conclusion
After playing with this a bit, I think these functions will make it into a future version of Universal to make it easier for working with Universal in VS Code. There are a host of other operations we could also add to make it even easier to work with other features of Universal directly from Code.