ZEE
ZEE

Reputation: 3193

Powershell environment variable

In a Powershell script (.ps1) Launched from the command line of a console (cmd.exe)

How can set and environment variable in the console,
so that when the Powershell script ends processing,
and exits to the console where was invoked...
the environment variable exists,
and can be read by a batch file,
or viewed with the SET command ?

do not want to set a 'Machine' or a 'User' variable...
only a console process variable...
the same variable you get if you use SET in the console

Upvotes: 1

Views: 578

Answers (1)

mklement0
mklement0

Reputation: 440679

To run a PowerShell script from cmd.exe invariably requires a (powershell.exe / pwsh.exe) child process, and child processes fundamentally cannot set environment variables for their parent process[1].

Your best bet is to have your *.ps1 file output the name and value of the desired environment variable and then have the calling cmd.exe process create it, based on that output.

Security note: Blindly defining environment variables based on the name-value pairs output by another command (a *.ps1 script, in your case) should only be done if you trust that command not to output malicious definitions.

Here's a simple example (run directly from an interactive cmd.exe session):

for /f "delims== tokens=1,*" %v in ('powershell.exe -c "'FOO=bar'"') do @set "%v=%w"

The above defines environment variable %FOO% with value bar, based on the PowerShell command outputting the literal name-value pair FOO=bar. Verify with echo %FOO%.

To extend this approach to defining multiple environment variables, make the command output each definition on its own line (which in PowerShell you can achieve by outputting an array of strings):

for /f "delims== tokens=1,*" %v in ('powershell.exe -c "'FOO=bar', 'BAZ=bam'"') do @set "%v=%w"

The above additionally defines %BAZ% with value bam.


To make this more convenient, I suggest creating a wrapper batch file (*.cmd) that performs the above:

  • Note that you'll have to use %%v and %%w instead of %v and %w there.

  • Instead of -c (for -Command) with the demo command, use -File with the path to your *.ps1 file to invoke it.

    • Also consider use of -NoProfile as well, to bypass loading of your PowerShell environment's $PROFILE file, which not only slows things down, but may pollute your command's output.

[1] As LotPings points out, child processes inherit copies of the parent process' environment variables. Modifications of these copies are never seen by the parent. A child process is fundamentally unable to modify its parent's environment, which is a restriction at the OS level - for good reasons: Modifying a running process' environment by an arbitrary (child) process would be a serious security concern.

Upvotes: 3

Related Questions