2012-07-19 60 views
2

我有一個MVC Web應用程序,它顯示了我們AD中用戶的一些信息。 AD與Office 365同步,因此使用UPN我可以使用Windows PowerShell cmdlets for Office 365從Office 365檢索許可證信息。基本上這一切都很好。不知道爲什麼C#PowerShell運行空間不規律地關閉

由於初始化cmdlet Connect-MsolService需要一些時間才能完成,因此我爲我的Office365Connector類使用了一種單例模式。在我的Global.asaxApplication_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字段以便稍後執行命令。這兩個字段將在Dispose方法PowerShellInvoker(當Office365Connector類正在處理時調用)中處理。腳本執行由該行代碼完成的:

_invoker.Invoke(scriptText); 

這麼多的介紹 - 現在,這裏是真正的問題:

在我的申請,我有一個用戶列表。當我點擊一個用戶時,使用AJAX請求加載附加信息。在此請求中,我的應用使用Office365Connector類的單例實例來檢索用戶的許可證信息。在大多數情況下,這一切都很完美。但是有時AJAX請求最終會以代碼500結束。調試我的源代碼時,我偶然發現上面「Invoke」行中的PowerShellInvoker中引發了異常,告訴我Runspace不再打開,而且我也無法找出原因。我甚至不能真正重現它。有時,當我單擊第二個用戶時發生錯誤。有時,錯誤發生在第10或第15個用戶。我已經想過MVC使用的一些奇怪的清理,超時或垃圾收集技術,但我還沒有得出結論。恕我直言,Runspace關閉不能基於時間,因爲「用戶點擊」之間的時間只有幾秒鐘。

Connect-MsolService cmdlet創建到Office 365的連接,但它不返回任何內容。因此,如果需要重新創建Runspace不是解決方法,因爲這將由PowerShellInvoker類完成,並且Office365Connector不會知道它必須重新連接到Office 365.(這也不會解決問題。 )結合這兩個類不是解決方案,因爲PowerShellInvoker也在其他地方使用。

那麼有誰能告訴我如何防止Runspace關閉或爲什麼關閉?

編輯:更多代碼

PowerShellInvoker類可以發現here

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)。我這樣做是因爲我想阻止枚舉類的惰性執行,因爲我認爲這可能是關閉的Runspace的原因。

+0

我沒有答案,但我有興趣試圖找出答案。是否有可能分享更多的代碼?另外,您是否嘗試在打開運行空間後立即啓動PowerShell腳本?看看它是否記錄了任何有用的內容會很有趣。 – 2012-07-19 17:14:49

+0

@ ElijahW.Gagne我編輯了這個問題並添加了更多的代碼。我會盡快嘗試記錄的想法。 – fero 2012-07-20 07:47:53

+0

感謝您的問題和答案 - 幫助我在爲PS提供商編寫測試時幫助我! – penderi 2012-10-31 09:54:40

回答

1

OK,這是我自己一個愚蠢的錯誤 - 儘管我真的不明白爲什麼MVC是這樣做的:

在我多次試圖解決的問題之一,我提出我的Office365Connector到的處置代碼應用程序的Dispose方法(在Global.asax.cs中)。之後,我顯然修復了原來的錯誤,但是由於處理的原因,它並沒有解決。顯然,應用程序實例比「結束」更經常處理。當我將代碼移回Application_End()時,它屬於一切正常。

這使得我的原始問題類型無效,因爲我寫我的配置代碼已經在Application_End()。 : - \

相關問題