.NET Environment Variables Not Applied (Windows)
🔍 Problem
You’ve instrumented a .NET application using the SeaLights agent, but the expected environment variables (e.g., SL_*
) are not being applied to the profiler process. This can lead to missing tags, incorrect configuration, or the profiler not activating.
Additionally, when defining variables using PowerShell, values may not appear immediately in the current session or may not propagate to background processes such as IIS or Windows Services.
⚠️ Cause
The environment variables may not be defined at the correct scope level for the profiler process to inherit them as Windows supports multiple levels of environment variables:
Machine-level: Available system-wide to all users and processes.
User-level: Available to all processes launched by a specific user.
Process-level (Session): Available only to the current shell or script session and its child processes.
When the same variable is defined at multiple levels, Windows resolves it using the following priority order:
Process-level > User-level > Machine-level
This means a variable set in the current session will override any user or machine-level definitions. However, suppose your profiler is launched as a service or from a different context (e.g., IIS, Windows Service). In that case, it may not inherit session-level variables at all — and will rely on user or machine-level definitions.
Common issues:
PowerShell changes are persisted to the registry, but not applied to the current
$env:
session unless reloaded manuallyServices (e.g., IIS) may not inherit session/user-level variables
Manual testing may work if variables are set at process level but fail in automated execution or services
🩺Diagnose
Use the following PowerShell function to log all SL_*
environment variables across the three key levels — Machine, User, and Process — to help diagnose where the variable is (or isn’t) defined.
function Get-SLEnvVarsAllLevels {
param (
[string]$OutputFilePath = "$(Get-Location)\sl_env_vars_all_levels.txt"
)
# Clear the file if it exists
if (Test-Path $OutputFilePath) { Clear-Content $OutputFilePath }
# Helper function to write to console and file
function Write-And-Log {
param ($text)
Write-Output $text
Add-Content -Path $OutputFilePath -Value $text
}
# Machine-level
Write-And-Log "`n=== Machine-level Environment Variables ==="
$machineVars = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
$machineVars.PSObject.Properties | Where-Object { $_.Name -like 'SL_*' } | ForEach-Object {
Write-And-Log "$($_.Name)=$($_.Value)"
}
# User-level
Write-And-Log "`n=== User-level Environment Variables ==="
$userVars = Get-ItemProperty -Path "HKCU:\Environment"
$userVars.PSObject.Properties | Where-Object { $_.Name -like 'SL_*' } | ForEach-Object {
Write-And-Log "$($_.Name)=$($_.Value)"
}
# Process-level
Write-And-Log "`n=== Process-level (Session) Environment Variables ==="
Get-ChildItem Env: | Where-Object { $_.Name -like 'SL_*' } | ForEach-Object {
Write-And-Log "$($_.Name)=$($_.Value)"
}
}
▶️ Usage:
Get-SLEnvVarsAllLevels -OutputFilePath "C:\Logs\env_debug.txt"
This will:
Print all
SL_*
variables to the console.Save them to a file for inspection or sharing with support.
✅ Solution
Use the following script to:
Set environment variables at the Machine level (persisted in registry)
Make them immediately available to the current PowerShell session (
$env:
scope)
$vars = @{
"SL_SESSION_TOKENFILE" = "your-agent-token-file"
"SL_SESSION_LABID" = "your-lab-id"
"SL_LOGDIR" = "my-logging-directory"
}
# Set at Machine level and apply in current session
$vars.GetEnumerator() | ForEach-Object {
[Environment]::SetEnvironmentVariable($_.Key, $_.Value, "Machine")
$env[$_.Key] = $_.Value
}
Write-Host "✅ Machine-level environment variables have been set and applied in current session."
If needed, replace "Machine"
with "User"
to define variables at the user level instead, or duplicate the logic to support both scopes.
📢Broadcast Environment Change (Optional)
The script above updates the current session, but other running apps (like explorer.exe
, new command prompts, etc.) may still use cached values.
To notify the operating system that environment variables have changed:
Advanced Option: Broadcast Update
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class NativeMethods {
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
}
"@
[void][NativeMethods]::SendMessageTimeout(
[IntPtr]0xFFFF, # HWND_BROADCAST
0x1A, # WM_SETTINGCHANGE
[UIntPtr]::Zero,
"Environment",
0x0002, # SMTO_ABORTIFHUNG
100,
[ref]([UIntPtr]::Zero)
)
Write-Host "Environment change broadcast sent to system."
This is useful in GUI environments or when other non-PowerShell apps need to immediately receive the updated environment without reboot.
Last updated
Was this helpful?