2

我正在尝试在 .netCore 上使用 C# 运行 PowerShell 脚本。

我现在尝试了许多不同的解决方案,但似乎没有一个有效。我只想执行一个 PowerShell 脚本并设置 ExecutionPolicies 和 Scope 以使其工作。但我总是遇到一个例外,即 ExecutionPolicies 不允许我以这种方式运行脚本。

尽管有实际的配置和代码,你会在下面找到,在到达.Invoke();之后,我没有从调试器那里得到任何反馈。被执行。等待响应并让软件在后台执行其操作总是会导致 stackoverflow 异常。

commandParameters 是一个简单的 Dictionary<string, string>

对此有什么想法吗?

干杯。


var iss = InitialSessionState.CreateDefault2();
        // Set its script-file execution policy.
        iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;
        iss.ExecutionPolicy = (ExecutionPolicy)Microsoft.PowerShell.ExecutionPolicyScope.CurrentUser;

        // Create a PowerShell instance with a runspace based on the 
        // initial session state.
        PowerShell ps = PowerShell.Create(iss);

 ps.AddCommand(path + "\\" + fileName);
        ps.AddParameters(commandParameters);
        var results = ps.InvokeAsync().GetAwaiter().GetResult();
4

1 回答 1

2
  • 分配给iss.ExecutionPolicy只控制当前进程的执行策略。

  • 不要分配值,因为它是Microsoft.PowerShell.ExecutionPolicyScope定义执行策略范围的相关枚举,仅与Set-ExecutionPolicyGet-ExecutionPolicycmdlet 相关。这个不相关枚举的数值恰好与适当的[Microsoft.PowerShell.ExecutionPolicy]枚举值重叠,因此策略范围 CurrentUser映射到策略 RemoteSigned(值0x1)。

    • 实际上,您的第二个 iss.ExecutionPolicy = ...分配会覆盖第一个分配并将流程范围执行策略设置为RemoteSigned.
    • 流程范围执行策略,即仅针对当前流程,是唯一可以通过初始会话状态设置的策略;有关如何更改持久范围的策略,请参阅下一节。

因此,iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted; *.ps1在手头的会话中调用文件就足够了-删除第二 iss.ExecutionPolicy = ...分配。


如果要持久修改执行策略,则必须使用.AddCommand('Set-ExecutionPolicy')适当的参数并调用该命令。警告

  • 更改持久的当前用户配置也会对相应 PowerShell 版本中的常规PowerShell 会话(交互式会话/CLI 调用)生效。

  • 相比之下,如果您更改持久机器配置 - 这需要使用提升(以管理员身份)运行:

    • 使用Windows PowerShell SDK,更改也会对常规 PowerShell 会话生效。
    • 使用PowerShell(Core) SDK,只对手头的SDK项目生效。[1]
  • 有关示例代码,请参阅此答案

警告

  • 如果当前用户/机器的执行策略是通过GPO(组策略对象)控制的,那么您基本上不能以编程方式覆盖它(通过 GPO 更改除外)。

  • 检查基于 GPO 的策略是否生效

    • 运行Get-ExecutionPolicy -List以按优先级降序列出为每个可用范围定义的策略。
    • 如果MachinePolicyUserPolicy范围的值不是Undefined则 GPO 策略有效(Get-ExecutionPolicy不带参数运行以查看当前会话的有效策略)。

基于 GPO 的策略阻止脚本文件执行时的有限解决方法

假设以下所有条件;脚本文件是指*.ps1文件:

  • 您的脚本文件不调用其他脚本文件。
  • 它(直接或间接)不加载导入时碰巧调用脚本文件的模块。
  • 您的脚本文件不依赖于知道它自己的位置(目录)或磁盘上的名称。

您可以将脚本文件的内容加载到字符串中,并将该字符串传递给 SDK 的.AddScript()方法,如以下简化示例所示:

using (var ps = PowerShell.Create()) {

  var results =
    ps.AddScript(File.ReadAllText(path + "\\" + fileName))
      .AddParameters(commandParameters)
      .Invoke();

}

[1] Windows PowerShell将执行策略存储在注册表中,常规会话和 SDK 都会参考这些策略。相比之下,PowerShell (Core)将它们存储在powershell.config.json文件中,在机器策略的情况下,它们与 PowerShell 可执行文件 (DLL) 一起存储。由于 SDK 项目有自己的可执行文件,因此常规 PowerShell(核心)安装的可执行文件看不到其附带的 JSON 文件。

于 2021-10-12T02:13:42.297 回答