【问题标题】:Invoking PowerShell cmdlets more quickly in C#在 C# 中更快地调用 PowerShell cmdlet
【发布时间】:2018-12-14 19:48:10
【问题描述】:

我能够使用 C# 中的 Powershell cmdlet 从 O365 获取用户详细信息。 问题是获取时间。太慢了。

每个用户需要 2 秒,所以如果我有大量用户,会导致时间问题。

在这里,我只想打印所有用户的信息,例如姓名、组详细信息、许可证。 我怎样才能更快地做到这一点?

试过一个:

        Runspace runspace = RunspaceFactory.CreateRunspace();
        runspace.Open();
        Pipeline UserDetailsPipe = runspace.CreatePipeline();
        UserDetailsPipe.Commands.AddScript("Get-AzureADUser");
        foreach (PSObject info in UserDetailsPipe.Invoke())  /////////*******
        {
            ArrayList Groups = new ArrayList();   // to hold memberOf
            ArrayList Licenses = new ArrayList(); // to hold of licenses

            string UserPrincipalName = info.Members["UserPrincipalName"].Value.ToString();
            string DisplayName = info.Members["DisplayName"].Value.ToString();

            //Getting MemberOf
            Pipeline memberPipe = runspace.CreatePipeline();
            memberPipe.Commands.AddScript("Get-AzureADUser -ObjectId '" + UserPrincipalName + "'| Get-AzureADUserMembership");

            //Getting Licenses
            Pipeline licensePipe = runspace.CreatePipeline();
            licensePipe.Commands.AddScript("$license = Get-AzureADUserLicenseDetail -ObjectId '" + UserPrincipalName + "' | select ServicePlans ");
            licensePipe.Commands.AddScript("$license.ServicePlans");


                foreach (var licensenames in licensePipe.Invoke())////////*****
                {
                    Licenses.Add(licensenames.Members["ServicePlanName"].Value.ToString());
                }

            foreach (var memberOf in memberPipe.Invoke())////////*******
            {
                Groups.Add(memberOf.Members["DisplayName"].Value.ToString());
            }
       }

我知道我正在调用许多管道。那么如何只使用一次调用来获得我的答案呢? (也可能在 PowerShell 类中)。

【问题讨论】:

  • 大概 O365 会有一个您可以使用的 API?
  • 我应该使用 PSCmdlets
  • 如果我使用PowerShell类,那也比上面的方法太慢了
  • 我得到了和你一样的结果,即使使用像 Get-Process 这样的东西。事实证明,我必须去删除 CustomPSHostRawUserInterface 和 CustomPsHostUI.cs 中的任何 throw NotImplementedExceptions。我不确定这里内部发生​​了什么,但我认为对于每个异常,System.Management.Automation 必须进行大量额外处理。运行代码时,观察调试输出窗口,看看是否有很多异常。然后运行另一个命令,例如 Get-ChildItem,它应该有更少的异常。 GCI 的执行时间要快得多。

标签: c# powershell azure office365 azure-active-directory


【解决方案1】:

看来最好的解决方案是组合成尽可能少的脚本以减少管道的数量。我还建议使用PowerShell 对象而不是Runspaces

另外,为了在调用后得到最终Collection 中的所有结果,请使用.AddStatement() 方法。这在下面演示。 Documentation for AddStatement

这需要根据您的环境进行修改,因为我只是简单地获取日期两次以演示将两个日期都返回到最终集合。

using (PowerShell powershell = PowerShell.Create()) {
    powershell.AddScript("Get-Date");
    powershell.AddStatement().AddScript("Get-Date");

    Collection<PSObject> result = powershell.Invoke();
}

【讨论】:

  • 如果我们在同一行使用分号(;)添加多个脚本,是否会影响PowerShell内存?
  • @saravananks 据我所知,您添加的脚本越多,PowerShell 消耗的内存就越多,但从您的应用程序的外观来看,这应该不是问题。你有记忆问题吗?
  • 我会添加更多语句,以便
  • @ivcbur 实际上内存概念在 powershell 中是如何工作的
  • 我找不到任何关于内存概念的文档
猜你喜欢
  • 2013-06-08
  • 1970-01-01
  • 2014-02-28
  • 1970-01-01
  • 2018-12-17
  • 2020-06-27
  • 2014-02-11
  • 1970-01-01
  • 2018-12-07
相关资源
最近更新 更多