C# 如何防止PowerShell更改环境变量?

C# 如何防止PowerShell更改环境变量?,c#,powershell,C#,Powershell,以下测试失败,因为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 Power

以下测试失败,因为
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对象/执行?

在注释中提供了关键指针:

由于环境变量本质上是[整个-]进程范围的,因此需要进程外运行空间来获得所需的行为

相比之下,
PowerShell.Create()
本身没有通过结果实例的
.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开始,创建一个名为
env:Path
的PowerShell变量,而不是修改环境变量
Path
;请参见

您是否尝试使用进程外运行空间而不是默认的进程内运行空间?@PetSerAl,是的,但调用
powerShell.Runspace.SessionStateProxy.PSVariable.Set(…)时,我得到了
System.Management.Automation.PSNotSupportedException
@Tar您无法访问远程
运行空间的
SessionStateProxy.PSVariable