我正在尝试用c#在。netcore上运行PowerShell脚本。
我已经尝试了许多不同的解决方案,但他们似乎都没有工作。我只是想执行一个PowerShell脚本,并设置ExecutionPolicies和Scope使其工作。但是我总是得到一个异常,ExecutionPolicies不允许我以这种方式运行脚本。
尽管使用下面的实际配置和代码,但在到达.Invoke();之后,我没有从调试器获得任何反馈是执行。等待响应并让软件在后台做它的事情总是会导致stackoverflow异常。
commandParameters是一个简单的Dictionary<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();
-
分配给
iss.ExecutionPolicy
只控制当前进程的执行策略. -
不分配
Microsoft.PowerShell.ExecutionPolicyScope
值,因为它是无关的枚举它定义了执行策略范围,仅与Set-ExecutionPolicy
和Get-ExecutionPolicy
cmdlet相关。这个不相关的枚举的数值恰好与相应的[Microsoft.PowerShell.ExecutionPolicy]
枚举值重叠,因此策略scopeCurrentUser
映射到策略RemoteSigned
(值0x1
)。- 实际上,您的第二个
iss.ExecutionPolicy = ...
赋值覆盖第一个赋值,并将进程范围执行策略设置为RemoteSigned
。 - 进程作用域执行策略,即对于当前进程只有,是唯一可以通过初始会话状态设置的策略;关于如何更改持久作用域的策略,请参阅下一节。
- 实际上,您的第二个
因此,iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;
单独足以在当前会话中调用*.ps1
文件-移除第二个iss.ExecutionPolicy = ...
赋值。
如果要持久修改执行策略,必须使用带有适当参数的.AddCommand('Set-ExecutionPolicy')
,并且调用该命令。警告:
-
更改持久当前用户配置也对常规PowerShell会话(交互会话/CLI调用)在相应的PowerShell版本中生效。
-
相反,如果您更改了持久的机器配置—这需要使用提升运行(作为admin):
- 使用Windows PowerShellSDK,此更改也对常规PowerShell会话生效。
- 使用PowerShell (Core)SDK,它只对手头的SDK项目生效[1]
-
查看示例代码的答案
警告:
-
如果当前用户/机器的执行策略是通过gpo(组策略对象)控制的,你基本上不能通过编程重写它(通过GPO更改除外)。
-
检查基于gpo的策略是否生效:
- 运行
Get-ExecutionPolicy -List
以优先级降序列出为每个可用范围定义的策略。 - 如果
MachinePolicy
或UserPolicy
作用域的值与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项目有自己的可执行文件,随之而来的JSON文件不是被定期PowerShell的可执行文件(核心)安装。