Product: PowerShell Universal Version: 2026.1.5
Hi, I have a general question about your experiences with the environments. I would like to switch many/all scripts to PowerShell 7, but I have noticed that the scripts take significantly longer (15 seconds or more), whereas PowerShell 5.1 is more efficient. I noticed that when starting a script, nothing happens at first. Then I see that PSU provides the following information: “Loading Active Directory module for Windows PowerShell with default drive ‘AD:’”. With Integrated, I have the problem that I can’t use credentials, so that’s not an option. With PowerShell 5.1 under the current version 2026.1.5, I have the problem that it can no longer read certificates, whereas PowerShell 7 has no issues with this. Do you have any tips for me to increase efficiency or improve performance?
Hi Marco,
Thank you for the detailed explanation. My name is Ruben Tapia, and I am a support engineer with Ironman Software.
What you are seeing is consistent with one of the main limitations of using PowerShell 7 together with modules that still rely on Windows PowerShell compatibility. In PSU, when Windows PowerShell Compatibility is triggered, an additional Windows PowerShell process is started for the runspace, which can noticeably increase startup time.
In your case, the message about loading the Active Directory module suggests that AD compatibility may be part of the delay. If your server supports ActiveDirectory module 1.0.1.0, that would be worth checking first, since that version has native PowerShell 7 support. Otherwise, PSU’s guidance is usually to keep AD-dependent workloads in Windows PowerShell 5.1 where needed.
You are also correct about another limitation: the Integrated environment is faster, but it does not support alternate credentials. If you need Run As, PSU supports that through PSCredential secret variables in non-Integrated environments.
To narrow this down, could you please share:
Verified references:
https://docs.powershelluniversal.com/config/environments https://docs.powershelluniversal.com/platform/modules https://docs.powershelluniversal.com/automation/scripts https://docs.powershelluniversal.com/config/running-as-a-service-account https://forums.ironmansoftware.com/t/windows-powershell-compatiblity-is-enabled-we-recommend-disabling-this-feature-of-powershell-when-using-powershell-universal/8686
Best regards,
Ruben Tapia
Hi @AnonymousUser ,
some requested information:
Hi @AnonymousUser . i ve made a change in the PS7 Environment Properties. I ve enabled the option Persistent Runspaces. Since then, after the first script startet, it takes 4-6 seconds. I think this is acceptable.
HI @AnonymousUser what could also be a “problem” is the background jobs powershell or .net is doing at startup. I have written a script some time ago to disable some of them in our environments (sometimes air gapped systems where only the powershell update check hangs for 5-10 seconds). Perhaps it is useful for you.
In general you only need the machine scope on servers, since we are also using this on our workstations, we are doing both. it fails with a warning if running as user (not administrator) and only applies user scope variables.
At the end, if you set $VerbosePreference = ‘Continue’before running the code, it will also output the found environment variables:
<#
.SYNOPSIS
Configure PowerShell and .NET environment variables for air-gapped environments.
.DESCRIPTION
This script configures environment variables to:
- Disable PowerShell telemetry
- Disable PowerShell update notifications
- Disable PowerShell diagnostics telemetry
- Disable .NET CLI telemetry
- Disable .NET welcome banners
- Reduce unnecessary module analysis cache cleanup activity
The script first tries to configure Machine scope.
If Machine scope fails, it falls back to User scope.
Official documentation:
PowerShell Environment Variables:
https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_environment_variables
PowerShell Telemetry:
https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_telemetry
PowerShell Update Notifications:
https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_update_notifications
PowerShell Startup Performance:
https://learn.microsoft.com/powershell/scripting/dev-cross-plat/performance/startup-performance
.NET CLI Telemetry:
https://learn.microsoft.com/dotnet/core/tools/telemetry
.NOTES
Recommended for:
- Air-gapped environments
- Offline systems
- Restricted enterprise environments
- CI/CD runners
- Non-interactive automation hosts
A restart of PowerShell sessions is required after applying changes.
#>
# Configure environment variables
$EnvironmentVariables = @{
POWERSHELL_TELEMETRY_OPTOUT = '1'
POWERSHELL_UPDATECHECK = 'Off'
POWERSHELL_DIAGNOSTICS_OPTOUT = '1'
DOTNET_CLI_TELEMETRY_OPTOUT = '1'
DOTNET_NOLOGO = 'true'
PSDisableModuleAnalysisCacheCleanup = '1'
}
# Configure preferred scope order
$Scopes = @(
'Machine'
'User'
)
# Apply environment variables
$AppliedScope = $null
foreach ($Scope in $Scopes) {
try {
Write-Verbose -Message ("Trying environment scope: {0}" -f $Scope)
foreach ($Variable in $EnvironmentVariables.GetEnumerator()) {
[System.Environment]::SetEnvironmentVariable(
$Variable.Key,
$Variable.Value,
$Scope
)
}
$AppliedScope = $Scope
Write-Verbose -Message (
"Successfully configured environment variables in scope: {0}" -f
$Scope
)
break
}
catch {
Write-Warning -Message (
"Failed to configure environment variables in scope '{0}'. {1}" -f
$Scope,
$_.Exception.Message
)
}
}
# Display configured variables by scope
foreach ($Variable in $EnvironmentVariables.Keys | Sort-Object) {
foreach ($Scope in $Scopes) {
$Value = [System.Environment]::GetEnvironmentVariable(
$Variable,
$Scope
)
Write-Verbose -Message (
"{0} = {1} [{2}]" -f
$Variable,
$Value,
$Scope
)
}
}