Background
NetCore 3.1 is set to reach EOL on December 3, 2022. In anticipation of this, users should upgrade to .NET 6, the current LTS version. .NET 6 is fully backwards-compatible going all the way back to NetCore 1.1, however the way it installs does change a bit. This installation change causes an issue with the Platform Configuration Tool when it runs its pre-installation checks.
Current Behavior
Pre-installation steps for installing on-prem Orchestrator are as follows:
-
Run the InstallRolesAndFeatures.ps1 script from the UiPath GitHub, which installs IIS and the appropriate IIS features.
-
Download and install the ASP.NET Core 3.1 Hosting Bundle
-
Install the URL Rewrite IIS plugin
-
Run the Platform Configuration Tool readiness check.
If the above steps are followed but the ASP.NET Core 3.1 Hosting Bundle is replaced with the ASP.NET Core Net6 Hosting Bundle, the Platform Configuration Tool will provide the following output:
> .\Platform.Configuration.Tool.ps1 -Readiness -SiteName "UiPath Orchestrator"
Validating 20.10 pre-installation requirements...
Checking AspNetCore hosting module...
ASP.NET Core Hosting Bundle V3.1 is required. Check that the ASP.NET Core Hosting Bundle is properly installed.
https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-3.1#install-the-net-core-hosting-bundle
Orchestrator is not installed. Can not perform the rest of platform pre-installation checks.
Platform readiness validations: 0 succeeded, 2 failed and 0 warning(s).
(Screenshot, for colored output)
Note there are two errors above:
-
The script reports the ASP.NET Core Hosting Bundle is not installed, even though we installed (a newer version of) it in a previous step.
-
Orchestrator is not installed, which is expected (this is pre-installation), but this reports as an error, which has caused confusion in the past.
There appear to be three conditions here:
-
Orchestrator is not installed. This reports as a failure but this behavior is not documented.
-
Orchestrator is installed, but is not the latest version. In this case, the pre-installation check behaves as documented, but it is not clear in the documentation under what conditions this behavior occurs.
-
Orchestrator is installed and is the latest version. This reports as a warning but this behavior is not documented.
Expected Behavior
Specifically, there are three major changes to be made here.
- The
Orchestrator.Checks.psm1
script, which holds theTest-WebCoreHostModuleInstallation
function, implies that version 3.1 or greater of the ASP.NET Core Hosting Bundle should be installed. However due to to reasons discussed below, this code does not function when versions newer than 3.1 are installed.
Where-Object {[Version]::new($_.PackageVersion) -ge [version]::new(3, 1)}
-
The decribed conditions above should be documented so that users know what output to expect.
-
If Orchestrator is not installed, which is expected for new installations, this should not report as an error. Reporting an error suggests the user has not satisfied the prerequisites for installing UiPath.
Resolution
The Test-WebCoreHostModuleInstallation
function source code is below (comments added):
function Test-WebCoreHostModuleInstallation {
Write-Host "Checking AspNetCore hosting module..."
$validationResult = [ValidationResult]::new()
# Ensure the AspNetCoreModuleV2 installed. Returns null if not found.
$aspNetCoreModule = Get-WebGlobalModule AspNetCoreModuleV2
# Add the path to the registry key for .NET Core
$netCoreHostingDirectoryRegistry = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Updates\.NET Core"
# If the AspNetCoreModuleV2 was not found or NetCore was not installed, we cannot continue.
if (-not $aspNetCoreModule -or -not (Test-Path $netCoreHostingDirectoryRegistry)) {
$errorMessage = "AspNetCoreModuleV2 not found. Check that the ASP.NET Core Hosting Bundle is properly installed."
$errorMessage += [Environment]::NewLine + "https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-3.1#install-the-net-core-hosting-bundle"
Write-ErrorMessage $errorMessage
$validationResult.Errors++
return $validationResult
}
# NetCore was installed. Look at all installations of NetCore.
$netCoreHostingBundleRegistryVersions = Get-ChildItem -path $netCoreHostingDirectoryRegistry -Recurse |
Where-Object { $_.Name -like '*Microsoft .NET Core *'} |
# Get the Package Version variable
Get-ItemProperty -Name "PackageVersion" |
# Get any where the version is newer than Version 3.1
Where-Object {[Version]::new($_.PackageVersion) -ge [version]::new(3, 1)}
# If no installed versions were greater than or equal to version 3.1, the install fails.
if ($netCoreHostingBundleRegistryVersions.Length -eq 0) {
$errorMessage = "ASP.NET Core Hosting Bundle V3.1 is required. Check that the ASP.NET Core Hosting Bundle is properly installed."
$errorMessage += [Environment]::NewLine + "https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-3.1#install-the-net-core-hosting-bundle"
Write-ErrorMessage $errorMessage
$validationResult.Errors++
return $validationResult
}
Write-SuccessMessage "AspNetCore hosting module is installed."
$validationResult.Successes++
return $validationResult
}
The above code implies that versions newer than NetCore 3.1 should work to satisfy the condition. However, starting in .NET 5, that registry key is no longer created. This means that although versions newer than NetCore 3.1 are valid, this script will not see that these versions are installed. There does not appear to be any sort of alternative registry key, so I referred to the Microsoft Documentation on checking which version of the .NET Runtime is installed. They suggest that you can call dotnet --list-runtimes
to get output such as this:
Microsoft.AspNetCore.All 2.1.7 [c:\program files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.13 [c:\program files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.7 [c:\program files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.13 [c:\program files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.0 [c:\program files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.0 [c:\program files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.0 [c:\program files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.7 [c:\program files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.13 [c:\program files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.0 [c:\program files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.0 [c:\program files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.0 [c:\program files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0 [c:\program files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.0 [c:\program files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.0 [c:\program files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.0 [c:\program files\dotnet\shared\Microsoft.WindowsDesktop.App]
My updated test function runs this application call, filters lines by entries for Microsoft.AspNetCore.App
, then ensures version 3.1 or newer is installed. This code is detailed below:
function Test-WebCoreHostModuleInstallation {
Write-Host "Checking AspNetCore hosting module..."
$validationResult = [ValidationResult]::new()
$aspNetCoreModule = Get-WebGlobalModule AspNetCoreModuleV2
if (-not $aspNetCoreModule) {
$errorMessage = "AspNetCoreModuleV2 not found. Check that the ASP.NET Core Hosting Bundle is properly installed."
# Changed to explicitly point to the .NET Core Hosting Bundle page since it has specific instructions.
$errorMessage += [Environment]::NewLine + "https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/hosting-bundle"
Write-ErrorMessage $errorMessage
$validationResult.Errors++
return $validationResult
}
# DotNet versions 5 and 6 do not create the HKLM:\\SOFTWARE\Wow6432Node\Microsoft\Updates\.NET Core regkey.
# This allows for us to check the installed runtime of the AspNetCore hosting module in a way that works on all versions.
$aspNetCoreRuntimes = dotnet --list-runtimes | Where-Object { $_.StartsWith("Microsoft.AspNetCore.App") }
# If nothing was returned, the hosting bundle is not installed.
if ($aspNetCoreRuntimes.Length -eq 0) {
$errorMessage = "ASP.NET Core Hosting Bundle V3.1 or newer is required. Check that the ASP.NET Core Hosting Bundle is properly installed."
$errorMessage += [Environment]::NewLine + "https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/hosting-bundle"
Write-ErrorMessage $errorMessage
$validationResult.Errors++
return $validationResult
}
# There may be multiple hosting bundles installed.
# We're not looking for the latest, we just want to make sure *any* are newer than or equal to 3.1.
foreach ($runtime in $aspNetCoreRuntimes)
{
# Split by string. Take the version at index 1. Parse to a System.Version instance.
$version = [Version]::Parse($runtime.Split(' ')[1])
if ($version -ge [Version]::New(3, 1))
{
Write-SuccessMessage "AspNetCore hosting module is installed."
$validationResult.Successes++
return $validationResult
}
}
# After trying all lines, we found nothing.
$errorMessage = "ASP.NET Core Hosting Bundle V3.1 or newer is required. Check that the ASP.NET Core Hosting Bundle is properly installed."
$errorMessage += [Environment]::NewLine + "https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/hosting-bundle"
Write-ErrorMessage $errorMessage
$validationResult.Errors++
return $validationResult
}
The only other change that is required here is in the main Platform.Configuration.Tool.ps1 script starting on line 265:
if (-not $OrchestratorInstallation) {
- Write-ErrorMessage "Orchestrator is not installed. Can not perform the rest of platform pre-installation checks."
- $validationResult.Errors++
+ Write-Host "Orchestrator is not installed. Skipping version upgrade pre-installation checks."
Write-ValidationResult $validationResult -ValidationSubject "Platform readiness"
return
}
This can be done as a warning message to get the user’s attention, but I think white text will stand out well enough sandwiched between two green lines. Additionally, a warning to me implies that something optional was not done but that aught to be done, whereas this is mostly just here to tell me that everything is good to go for an initial install.
After these changes are made, the corresponding documentation can be changed to provide further information about the expected output in each of the three aforementioned conditions.