簡體   English   中英

如何防止 PowerShell 更改環境變量?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM