[英]How to prevent PowerShell from changing environment variables?
以下测试失败,因为PowerShell
对象更改了调用者进程的路径:
using System;
using System.IO;
using System.Linq;
using System.Management.Automation;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Helpers.Tests.ShellHelper {
[TestClass]
public class PowerShellEnvAlteration_Tests {
[TestMethod]
public void TestPath() {
var searchTarget = @"C:\LandingZone";
using (PowerShell powerShell = PowerShell.Create()) {
powerShell.Runspace.SessionStateProxy.SetVariable("env:Path",
$"{searchTarget}{Path.PathSeparator}{Environment.GetEnvironmentVariable("PATH")}");
}
var pathDirs = Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator);
Assert.IsFalse(pathDirs.Contains(searchTarget));
}
}
}
我该如何预防? 是否可以完全隔离此PowerShell
对象/执行?
PetSerAl在评论中提供了关键指针:
因为环境变量本质上是 [whole-]进程范围的,所以您需要一个进程外运行空间来获得所需的行为。
相比之下, PowerShell.Create()
本身,没有通过结果实例的.Runspace
属性显式分配运行.Runspace
,默认为进程内运行空间,并且通过该运行空间修改环境变量,然后总是影响运行在相同过程也是如此。
要修改代码以使用进程外运行空间,请执行以下操作:
// ...
using System.Management.Automation.Runspaces;
// ...
// Create an out-of-process runspace...
using (var runspace = RunspaceFactory.CreateOutOfProcessRunspace(null))
{
runspace.Open(); // ... open it ...
using (PowerShell powerShell = PowerShell.Create())
{
powerShell.Runspace = runspace; // ... and assign it to the PowerShell instance.
// Now setting $env:PATH only takes effect for the separate process
// in which the runspace is hosted.
// Note: `powerShell.Runspace.SessionStateProxy.SetVariable("env:Path", ...)` does
// does NOT work with OUT-OF-PROCESS runspaces, so a call to
// `Set-Item env:PATH ...` is used to modify the other process' PATH env. var.
// (Environment.SetEnvironmentVariable() is NOT an option, because
// it would modify the *calling* process' environment).
powerShell.AddCommand("Set-Item")
.AddParameter("LiteralPath", "env:Path")
.AddParameter("Value", $"{searchTarget}{Path.PathSeparator}{Environment.GetEnvironmentVariable("Path")}")
.Invoke();
powerShell.Commands.Clear();
// ...
}
}
注意:上面使用了对Set-Item env:Path ...
的调用来修改进程外运行空间中的$env:PATH
,因为正如 PetSerAl 指出的那样,与进程内运行空间不同,使用powerShell.Runspace.SessionStateProxy.SetVariable("env:Path", ...)
从 Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.3 开始powerShell.Runspace.SessionStateProxy.SetVariable("env:Path", ...)
创建一个字面命名的PowerShell变量env:Path
而不是修改环境变量PATH
; 看到这个 GitHub 问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.