繁体   English   中英

是否可以从 C# 运行 PowerShell shell 并使其保持运行,同时(同步)在其中执行多个 PowerShell 脚本?

[英]Is it possible to run the PowerShell shell from C# and keep it running, while (synchronously) executing multiple PowerShell scripts within it?

问题:

  1. 是否可以从 C# 运行 PowerShell shell 并使其保持运行,同时(同步)从同一个 C# 应用程序在此 shell 中执行多个 PowerShell 脚本?
  2. 或者,在 .NET Core 应用程序中使用 PowerShell 类(来自 System.Management.Automation.Powershell 命名空间)时,是否可以使用 Windows PowerShell(版本 5)而不是默认的 PowerShell Core(版本 7)执行脚本?

背景:

我们正在将现有的 .NET Framework 4.8 应用程序(当前应用程序)重建为新的 ASP.NET Core 应用程序(新应用程序)。 在当前应用程序中,使用 PowerShell 类(在 System.Management.Automation.Powershell 命名空间中),我们执行一个 PowerShell 脚本(然后在 Windows PowerShell 5 中执行)它调用 Exchange 开始创建邮箱(使用enable-remotemailbox命令; Exchange 安装在运行当前应用程序和执行 PowerShell 脚本的同一台服务器上)。 每次(一般一天几十次)要创建一个邮箱,PowerShell脚本都是这样执行的。

我们对当前应用程序的经验是,仅第一次运行 Exchange 命令(在本例中为 enable-remotemailbox)时,大约需要15 秒 只要 C# 应用程序正在运行(或者,在 C# 应用程序之外,但在 PowerShell 内并且只要 PowerShell shell 处于打开状态),后续的 Exchange 命令就会运行得非常快,大约需要 200 毫秒(显然是由于某些设置/缓存/ ...? 仅在第一次执行脚本时)。

我们希望通过新应用程序实现相同的功能:

  1. 使 PowerShell 运行现有脚本以创建邮箱。
  2. 达到与当前应用程序相似的速度。
  3. 拥有稳定可靠的邮箱创建功能。

我首先尝试使用 PowerShell 类,就像我们在当前应用程序中使用的那样,但由于 Windows PowerShell(版本 5)是基于 .NET Framework 构建的,而 PowerShell Core(版本 7)是基于 .NET Core 构建的,因此新的应用程序是一个 .NET Core 应用程序,当使用 PowerShell 类时,我们(显然)会自动使用 PowerShell Core 来执行脚本。 但是,我相信我可以得出结论,无法在 PowerShell Core 中运行 enable-remotemailbox 命令(在 Windows PowerShell 中,在添加管理单元后,脚本的其余部分中可以使用 enable-remotemailbox,但管理单元PowerShell Core 中不再存在,而且我找不到替换管理单元的模块)。

接下来,我尝试使用 Process 类(来自 System.Diagnostics.Process 命名空间),方法是启动 Windows PowerShell(版本 5)进程并在其中执行脚本。 尽管这有效,但每次 enable-remotemailbox 命令运行时大约需要 15 秒,而不仅仅是第一次。

有一种替代方案很可能满足所有需求(即速度需求),当我上面两个问题的答案都是“否”时,我们将使用它,即使用 .NET Framework Windows 服务我们将能够从 .NET Core 应用程序调用。 然而,这似乎在不必要的时候会涉及到一些开销; 因此,我首先要寻找上述 2 个问题的答案。

您遇到的最初 15 秒可能是由于会话中缺少 Powershell 模块造成的。 第一次执行 ps 时,它会被加载。 因此额外的 15 秒。

使用 powershell sdk 7,您现在正在运行一个完整的 ps 主机。 在您之前的项目中,您只使用 System.Management.Automation.Powershell 程序集“附加”到 ps5。 该软件包使用您在主机上安装的 ps 并且该 ps 可能已经预加载了 15second 模块。 这就是为什么你会体验到这种差异。

您可以通过预加载您需要的模块来配置您的 powershell 执行。 这是一个代码片段:

    // a singleton in my project
    public class Runspace
    {
        public RunspacePool Pool { get; }

        public Runspace()
        {
            var session = InitialSessionState.CreateDefault();
            session.ImportPSModule("ActiveDirectory");
            Pool = RunspaceFactory.CreateRunspacePool(session);
        }
    }

    public class PsExecutor
    {
        private readonly Runspace _runspace;

        public PsExecutor(Runspace runspace)
        {
            _runspace = runspace;
        }

        public void Exec()
        {
            using (PowerShell ps = PowerShell.Create())
            {
                ps.RunspacePool = _runspace.Pool;
                ps.AddStatement().AddCommand("Get-ADUser").AddParameters();
                ps.Invoke();
            }
    }

您可以记录 Runspace 的构造函数消耗的时间。 并将其与您现在体验的 15 秒进行比较。 解决方案的优点:您可以控制构造函数的执行。

暂无
暂无

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

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