在C#中更快地调用PowerShell cmdlets

5

我可以使用C#中的Powershell cmdlets从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可以使用,对吧? - Stevo
我应该使用PSCmdlets进行工作。 - saravanan ks
如果我使用 PowerShell 类,那也比上面的方法慢。 - saravanan ks
我得到了和你一样的结果,即使使用Get-Process之类的东西。结果证明,我必须去除CustomPSHostRawUserInterface和CustomPsHostUI.cs中所有的throw NotImplementedExceptions。我不确定这里的内部情况,但我认为对于每个异常,System.Management.Automation必须做很多额外的处理。在运行代码时,请注意您的调试输出窗口,并查看是否有许多异常。然后运行另一个命令,如Get-ChildItem,它应该有更少的异常。GCI的执行时间要快得多。 - Devon Dieffenbach
1个回答

1

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

此外,为了在调用后获取所有结果到最终的Collection中,请使用.AddStatement()方法。下面演示了这一点。AddStatement文档

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

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

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

如果我们使用分号(;)在同一行中添加多个脚本,会影响PowerShell的内存吗? - saravanan ks
据我所知,您添加的脚本越多,PowerShell 将消耗更多的内存,但从您的应用程序的外观来看,这不应该是一个问题。您是否遇到了内存问题? - ivcubr
我会添加更多语句,以便... - saravanan ks
@ivcbur 实际上,在PowerShell中,内存概念是如何工作的? - saravanan ks
我找不到任何关于内存概念的文档。 - saravanan ks
据我所知,这只是 PowerShell“命令行”界面的接口,因此内存行为将类似于手动从 PowerShell 提示符运行这些命令时的行为。由于C#对象,会有轻微的额外开销。如果您对更具体的信息感兴趣,最好直接提出另一个问题。 - ivcubr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接