Environment Variables Helper
Provides helper methods for reading and writing environment variables at both user and machine scope.
Using this static class to read/write environment variable avoid the issue of settings a variable with the classic Environment.SetEnvironmentVariable, where a variable value is not immediately available after it’s set.
- Writes are performed directly to the Windows Registry.
- After changes, a broadcast message is sent to notify the system of the update.
- Supports both machine-wide and per-user environment variables.
VB
Imports System.Runtime.InteropServices
Imports Microsoft.Win32
Public NotInheritable Class EnvVarHelper
' Broadcast message to notify the system that environment variables have changed
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function SendMessageTimeout(
hWnd As IntPtr,
Msg As UInteger,
wParam As UIntPtr,
lParam As String,
fuFlags As UInteger,
uTimeout As UInteger,
ByRef lpdwResult As UIntPtr) As IntPtr
End Function
Private Const HWND_BROADCAST As Integer = &HFFFF
Private Const WM_SETTINGCHANGE As UInteger = &H1A
Private Const SMTO_ABORTIFHUNG As UInteger = &H2
' Registry paths for Machine and User environment variables
Private Const MachineEnvKeyPath As String = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Private Const UserEnvKeyPath As String = "Environment" ' under HKEY_CURRENT_USER
''' <summary>
''' Sets or updates a system-wide (machine-level) environment variable.
''' </summary>
''' <category>Methods</category>
''' <param name="varName">The name of the environment variable to set.</param>
''' <param name="value">The value to assign to the variable.</param>
''' <remarks>
''' <list type="bullet">
''' <item><description>Writes to HKEY_LOCAL_MACHINE, under the standard environment key.</description></item>
''' <item><description>Requires administrative privileges to succeed.</description></item>
''' <item><description>Broadcasts WM_SETTINGCHANGE to inform the system of the update.</description></item>
''' </list>
''' </remarks>
Public Shared Sub SetMachineEnvVar(varName As String, value As String)
Using key As RegistryKey = Registry.LocalMachine.OpenSubKey(MachineEnvKeyPath, writable:=True)
If key Is Nothing Then
Throw New InvalidOperationException("Cannot open the Machine Environment registry key.")
End If
' Write REG_SZ
key.SetValue(varName, value, RegistryValueKind.String)
End Using
NotifyEnvironmentChanged()
End Sub
''' <summary>
''' Retrieves the value of a system-wide (machine-level) environment variable.
''' </summary>
''' <category>Methods</category>
''' <param name="varName">The name of the environment variable to retrieve.</param>
''' <returns>The value of the environment variable, or <c>Nothing</c> if not found.</returns>
''' <remarks>
''' <list type="bullet">
''' <item><description>Reads from HKEY_LOCAL_MACHINE under the environment key.</description></item>
''' <item><description>Returns null if the variable does not exist or the registry key is missing.</description></item>
''' </list>
''' </remarks>
Public Shared Function GetMachineEnvVar(varName As String) As String
Using key As RegistryKey = Registry.LocalMachine.OpenSubKey(MachineEnvKeyPath, writable:=False)
If key Is Nothing Then Return Nothing
Dim raw As Object = key.GetValue(varName, Nothing)
If raw Is Nothing Then Return Nothing
Return Convert.ToString(raw)
End Using
End Function
''' <summary>
''' Sets or updates a per-user environment variable.
''' </summary>
''' <category>Methods</category>
''' <param name="varName">The name of the environment variable to set.</param>
''' <param name="value">The value to assign to the variable.</param>
''' <remarks>
''' <list type="bullet">
''' <item><description>Writes to HKEY_CURRENT_USER under the Environment key.</description></item>
''' <item><description>Does not require administrative rights.</description></item>
''' <item><description>Sends WM_SETTINGCHANGE message to notify the system.</description></item>
''' </list>
''' </remarks>
Public Shared Sub SetUserEnvVar(varName As String, value As String)
Using key As RegistryKey = Registry.CurrentUser.OpenSubKey(UserEnvKeyPath, writable:=True)
If key Is Nothing Then
Throw New InvalidOperationException("Cannot open the User Environment registry key.")
End If
' Write REG_SZ
key.SetValue(varName, value, RegistryValueKind.String)
End Using
NotifyEnvironmentChanged()
End Sub
''' <summary>
''' Retrieves the value of a per-user environment variable.
''' </summary>
''' <category>Methods</category>
''' <param name="varName">The name of the environment variable to retrieve.</param>
''' <returns>The value of the environment variable, or <c>Nothing</c> if not found.</returns>
''' <remarks>
''' <list type="bullet">
''' <item><description>Reads from HKEY_CURRENT_USER under the Environment key.</description></item>
''' <item><description>Returns null if the variable does not exist or access is denied.</description></item>
''' </list>
''' </remarks>
Public Shared Function GetUserEnvVar(varName As String) As String
Using key As RegistryKey = Registry.CurrentUser.OpenSubKey(UserEnvKeyPath, writable:=False)
If key Is Nothing Then Return Nothing
Dim raw As Object = key.GetValue(varName, Nothing)
If raw Is Nothing Then Return Nothing
Return Convert.ToString(raw)
End Using
End Function
Private Shared Sub NotifyEnvironmentChanged()
Dim result As UIntPtr = UIntPtr.Zero
SendMessageTimeout(CType(HWND_BROADCAST, IntPtr),
WM_SETTINGCHANGE,
UIntPtr.Zero,
"Environment",
SMTO_ABORTIFHUNG,
5000,
result)
End Sub
End Class