繁体   English   中英

从 c# 运行 Powershell 脚本

[英]Running a Powershell script from c#

我正在尝试从 C# 代码运行 PowerShell 脚本,但我遇到了一些(可能是环境)问题:

在我尝试运行它的机器上,发生以下情况:

  1. PowerShell 以管理员身份启动并加载
  2. PowerShell window 立即关闭(显然)没有错误

笔记:

  • 该脚本有效。 当我从 ISE 运行它时,它运行没有错误。
  • 如果我右键单击脚本并选择使用 PowerShell 运行,即使我没有在脚本中更改它,我也会收到执行策略错误。

Set-ExecutionPolicy: Windows PowerShell 已成功更新您的执行策略,但该设置被更具体的 scope 中定义的策略覆盖。由于覆盖,您的 shell 将保留其当前有效的 RemoteSigned 执行策略。 键入“Get-ExecutionPolicy -List”以查看您的执行策略设置。 更多信息请参见“Get-Help Set-ExecutionPolicy”。 在第 1 行 char:46 + if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process... + ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ + CategoryInfo: PermissionDenied: (:) [Set-ExecutionPolicy], SecurityException + FullyQualifiedErrorId: ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand

  • 获取执行策略列表

     Scope ExecutionPolicy ----- --------------- MachinePolicy Unrestricted UserPolicy Undefined Process Bypass CurrentUser Unrestricted LocalMachine Unrestricted
  • 我认为这是环保的,因为:

    • 前几天还好好的
    • 在其他电脑上运行正常

这是我用来调用脚本的代码:

if (File.Exists("Start.ps1"))
{
    string strCmdText = Path.Combine(Directory.GetCurrentDirectory(), "Start.ps1");

    var process = System.Diagnostics.Process.Start(@"C:\windows\system32\windowspowershell\v1.0\powershell.exe ", strCmdText);
    process.WaitForExit();
}

脚本本身无关紧要,因为我已将其更改为简单的

Write-Host "Hello"
$d=Read-Host

我有同样的问题。

问题出在脚本的路径上。 它在这台特定的机器上有空间,我没有处理过。

窗口关闭太快,看不到任何错误,但设置

process.StartInfo.RedirectStandardOutput = true;

帮助我抓住它。

执行策略与我的错误无关。

为了解决这个问题,我改变了c#代码中的路径,如下所述: 在CMD.EXE中从“路径中存在非法字符”的位置执行Powershell脚本

完整代码:

if (File.Exists("Start.ps1"))
            {
                File.GetAttributes("Start.ps1");
                string strCmdText =   Path.Combine(Directory.GetCurrentDirectory(), "Start.ps1");
                var process = new Process();
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.FileName = @"C:\windows\system32\windowspowershell\v1.0\powershell.exe";
                process.StartInfo.Arguments = "\"&'"+strCmdText+"'\"";

                process.Start();
                string s = process.StandardOutput.ReadToEnd();
                process.WaitForExit();

                using (StreamWriter outfile = new StreamWriter("StandardOutput.txt", true))
                {
                    outfile.Write(s);
                }

            }

当您列出策略时,显然有一个针对您的计算机实施的组策略(即使它不在域中,仍然有本地GP生效)将MachinePolicy更改为“RemoteSigned”,这超出了所有本地设置的策略,这是在代码执行方面比“Unrestricted”更强大的策略。 如果您的PC位于域中,则可以以本地管理员身份运行“策略的结果集(日志记录)”,并获取影响PC的域策略。 如果没有,请从“控制面板”/“管理工具”运行“本地安全策略”,然后导航“计算机配置 - 管理模板 - Windows组件 - Windows PowerShell”并检查其中的策略值(“启用方案执行” - 大致从本地化翻译),如果需要,你可以改变那里的价值。 完成后,重新加载Powershell。

首先要做的事情是:从 .NET 可执行文件执行 PowerShell 代码的另一种更有效和灵活的方法是使用PowerShell SDK ,它可以在进程内执行完整的 .NET 类型支持- 请参阅此答案以获取示例。


虽然您自己的答案提供了一个有效的解决方案,但还有一个更简单的解决方案也适用于恰好包含'字符的脚本文件路径:

为了通过powershell.exe 、Windows PowerShell CLI 执行.ps1文件,请使用其 -File -File "..." ,如果您使用.Arguments (.Arguments (. NET Framework) / 将脚本文件路径按原样传递给.ArgumentList.Add() (.NET (Core)),并允许您在需要时将任何传递 arguments 指定为文字(带有嵌入式双引号):

# ... 
string strCmdText = Path.Combine(Directory.GetCurrentDirectory(), "Start.ps1");
var process = new Process();
process.StartInfo.UseShellExecute = false;
# ...
process.StartInfo.FileName = @"C:\windows\system32\windowspowershell\v1.0\powershell.exe";
// Use '-File' with embedded "..." quoting.
process.StartInfo.Arguments = string.Format("-File \"{0}\"", strCmdText);
// In a .NET Core / .NET 5+ application you can alternatively use:
//   process.StartInfo.ArgumentList.Add("-File");
//   process.StartInfo.ArgumentList.Add(strCmdText);
# ...

笔记:

  • 如果未指定powershell.exe -File -Command作为目标参数,在从所有后续 arguments 中剥离(未转义) "之后,它们解释为 PowerShell 代码- 请参阅此答案以获取背景信息。

  • 有关 PowerShell CLI 的全面概述,在两个 PowerShell 版本中,请参阅此答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM