gpt4 book ai didi

c# - 不知道为什么 C# PowerShell Runspace 不定期关闭

转载 作者:太空宇宙 更新时间:2023-11-03 13:57:55 25 4
gpt4 key购买 nike

我有一个 MVC 网络应用程序,它显示了我们 AD 中用户的一些信息。 AD 与 Office 365 同步,因此使用 UPN 我可以使用 Windows PowerShell cmdlets for Office 365 从 Office 365 检索许可证信息.基本上这一切都很好。

由于初始化 cmdlet Connect-MsolService 需要一些时间才能完成,因此我为我的 Office365Connector 类使用了一种单例模式。在我的 Global.asax 中,在 Application_Start() 中,我初始化了单例实例,在 Application_End() 中,我处理了它。连接器类只使用我的 PowerShellInvoker 类的一个实例,顾名思义,它封装了 PowerShell 调用。 PowerShellInvoker 构造函数中的 PowerShell 初始化代码如下所示:

public PowerShellInvoker(params string[] modules)
{
var iss = InitialSessionState.CreateDefault();
iss.ImportPSModule(modules);
iss.ThrowOnRunspaceOpenError = true;

_runspace = RunspaceFactory.CreateRunspace(iss);
_runspace.Open();
_invoker = new RunspaceInvoke(_runspace);
}

Office365Connector 类使用 "MSOnline" 作为参数调用此构造函数。 MSOnline 模块包含 Office 365 的 cmdlet。我保留 _runspace_invoker 字段以供稍后执行命令。这两个字段都将在 PowerShellInvokerDispose 方法中释放(在释放 Office365Connector 类时调用)。脚本执行由这行代码完成:

_invoker.Invoke(scriptText);

介绍了这么多 - 现在真正的问题来了:

在我的应用程序中,我有一个用户列表。当我单击某个用户时,会使用 AJAX 请求加载其他信息。在此请求中,我的应用程序使用 Office365Connector 类的单例实例来检索用户的许可证信息。在大多数情况下,这一切都很完美。但有时 AJAX 请求以代码 500 结束。调试我的源代码时,我偶然发现在上面“Invoke”行的 PowerShellInvoker 中抛出异常,告诉我运行空间未打开不再,我不明白为什么。我什至无法真正重现它。有时,当我单击第二个用户时会发生错误。有时,错误发生在第 10 个或第 15 个用户上。我已经想到了 MVC 使用的一些奇怪的清理、超时或垃圾收集技术,但我还没有得出结论。恕我直言,Runspace 关闭不能基于时间,因为“用户点击”之间的时间只有几秒钟。

Connect-MsolService cmdlet 创建到 Office 365 的连接,但它不返回任何内容。因此,如果需要重新创建运行空间不是解决方法,因为这将由 PowerShellInvoker 类完成,而 Office365Connector 不知道它必须重新连接到Office 365。(这也不会解决问题。)将这两个类结合起来也不是解决方案,因为 PowerShellInvoker 也在别处使用。

那么谁能告诉我如何防止 Runspace 关闭或关闭的原因?

编辑:更多代码

可以找到完整的 PowerShellInvokerhere .

Office365Connector 类中,目前有很多开销。以下是一些片段:

在构造函数中初始化:

var cred = new PSCredential(adminUpn, adminPassword);

_psi = new PowerShellInvoker("MSOnline");
_psi.ExecuteCommand("Connect-MsolService", new { Credential = cred });

获取 UPN 许可证的方法:

public IEnumerable<string> GetUserLicenses(string upn)
{
PSObject[] licenses = _psi.ExecuteScript(string.Format("(Get-MsolUser -UserPrincipalName \"{0}\").Licenses | % {{ $_.AccountSkuId }}", upn)).ToArray();

// no licenses: a list with one element (which is null) is returned.
if (licenses.Length == 1 && licenses[0] == null)
{
licenses = new PSObject[0];
}

return licenses.Select(pso => pso.ToString()).ToList();
}

如您所见,我向方法返回值添加了一些 ToList(尤其是在 PowerShellInvoker 中)。我这样做是因为我想防止枚举项的延迟执行,因为我认为这可能是关闭运行空间的原因。

最佳答案

好吧,这是我自己犯的一个愚蠢的错误——虽然我真的不明白为什么 MVC 这样做:

在我多次尝试解决问题的过程中,我将 Office365Connector 的处理代码移到了应用程序的 Dispose 方法(在 Global.asax 中.cs).在那之后,我显然修复了原来的错误,但由于处理的问题,它没有解决。显然,应用程序实例的处理次数比“结束”次数多。当我将代码移回它所属的 Application_End() 时,一切正常。

这让我原来的问题有点无效,因为我写道我的处置代码已经在 Application_End() 中。 :-\

关于c# - 不知道为什么 C# PowerShell Runspace 不定期关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11564774/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com