I have a Perl-based logon script that needs to set the user's environment variables. However, whenever I modify the %ENV hash, the changes are only temporary. How can I make these changes persist for the duration of the user's logon session?

Whenever a Windows OS creates a process, the OS provides the process with a copy of the Windows environment. To create this copy, the OS extracts information such as system and user environment variables from the registry and stuffs this information into the application's process space. Every process that runs has its own copy of the environment.

Any process can modify these variables in its copy of the environment. Perl lets you modify them by exposing each variable as a key in the %ENV hash. For example, you can append a new directory to the PATH environment variable with the code

$ENV\{'PATH'\} =
  "$ENV\{'PATH'\};C:\\Temp";

However, this code changes the PATH environment variable only in the Perl process's copy of the environment. This variable isn't changed in the environment of Perl's parent command console, even though the console spawned the Perl process. Likewise, no other processes are affected because they have no way of knowing that you made this alteration, which means that only your script will be affected by the change (and any processes that the script might spawn). After the Perl script ends, the change is no longer valid. Even if you run a new Perl script, the new Perl process inherits a fresh, unaltered copy of the environment from its parent command console.

However, you can make a persistent, systemwide change of an environment variable by calling the Win32::AdminMisc::SetEnvVar() function. This function not only modifies the variable in the registry but also sends a systemwide message announcing the change.

For example, you can modify the user's PATH variable with the code

Win32::AdminMisc::SetEnvVar(
  "PATH", "$ENV\{'PATH'\};C:\\Temp",
  ENV_USER );

Processes that are listening for such messages will respond to this function call by reloading a fresh copy of the environment. However, neither the current Perl process nor the command console will reload a fresh copy. So, if you need to use the modified variable after you've called the SetEnvVar() function, you need to either update the %ENV hash or rerun the Perl script.