1

我在PowerShell中編寫了一個必須重定向程序集綁定的PowerShell模塊。 我在使用powershell_ise.exe.config中的bindingRedirect時沒有問題,但我不認爲這是可接受的模塊,我想分發,所以我尋找其他方式,並遇到AppDomain.CurrentDomain.AssemblyResolvePowerShell中的StackOverflowException當tab-completion/Intellisense被調用時

我目前使用這個在我.psm1文件的頂部:

function Resolve-AssemblyRedirect { 
    PARAM ([object]$sender, [System.ResolveEventArgs]$e) 
    PROCESS { 
     $requestedName = New-Object System.Reflection.AssemblyName $e.Name 
     if ($requestedName.Name -eq "System.Net.Http.Primitives") { 
      return [System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assemblies\System.Net.Http.Primitives.dll") 
     } 

     return $null 
    } 
} 

if (-not $Global:MODULE_LOADED) { 
    [AppDomain]::CurrentDomain.add_AssemblyResolve({ Resolve-AssemblyRedirect $Args[0] $Args[1] }) 
    Set-Variable -Option Constant -Name MODULE_LOADED -Value $true -Scope Global 
} 

我可以使用Tab補齊/智能感知在ISE相當可靠地觸發問題。我也看到它在殼中。當我相當可靠地說,它並不總是相同的cmdlet觸發它。例如,在準備工作時,我用Get-ADUser [tab]觸發了它,最近我輸入了get-por [tab],Intellisense顯示了Get-GPOReport,然後掛起。

如果我註釋掉[AppDomain] ::開始的行,並且敲完tab,我沒有看到問題。

在我繼續之前,我想指出的是,之前我從來沒有必要在PowerShell中調試過任何東西,所以在黑暗中已經有相當多的摸索。爲了調試,我加了REG_SZHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug名爲Auto和價值1,這是給我的選項來啓動VS 2012,其隨後向我展示:

System.StackOverflowException了未處理

,當我看調用堆棧我看到:

mscorlib.dll!System.Resources.ResourceManager.GetString(string name, System.Globalization.CultureInfo culture) + 0x23c bytes  
System.Management.Automation.dll!System.Management.Automation.ErrorCategoryInfo.Ellipsize(System.Globalization.CultureInfo uiCultureInfo, string original) + 0x88 bytes 
System.Management.Automation.dll!System.Management.Automation.ScriptBlock.InvokeAsDelegateHelper(object dollarUnder, object dollarThis, object[] args) + 0x137 bytes  
[Lightweight Function] 
mscorlib.dll!System.AppDomain.OnAssemblyResolveEvent(System.Reflection.RuntimeAssembly assembly, string assemblyFullName) + 0xbc bytes 
[Native to Managed Transition] 
[Managed to Native Transition] 
mscorlib.dll!System.Reflection.RuntimeAssembly.InternalGetSatelliteAssembly(string name, System.Globalization.CultureInfo culture, System.Version version, bool throwOnFileNotFound, ref System.Threading.StackCrawlMark stackMark) + 0x3ab bytes 
mscorlib.dll!System.Resources.ManifestBasedResourceGroveler.GetSatelliteAssembly(System.Globalization.CultureInfo lookForCulture, ref System.Threading.StackCrawlMark stackMark) + 0xdd bytes 
mscorlib.dll!System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(System.Globalization.CultureInfo culture, System.Collections.Generic.Dictionary<string,System.Resources.ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists, ref System.Threading.StackCrawlMark stackMark) + 0xe2 bytes 
mscorlib.dll!System.Resources.ResourceManager.InternalGetResourceSet(System.Globalization.CultureInfo requestedCulture, bool createIfNotExists, bool tryParents, ref System.Threading.StackCrawlMark stackMark) + 0x329 bytes 
mscorlib.dll!System.Resources.ResourceManager.InternalGetResourceSet(System.Globalization.CultureInfo culture, bool createIfNotExists, bool tryParents) + 0x23 bytes  
mscorlib.dll!System.Resources.ResourceManager.GetString(string name, System.Globalization.CultureInfo culture) + 0x23c bytes  
Microsoft.PowerShell.Editor.dll!Microsoft.VisualStudio.Language.Intellisense.Implementation.CompletionSession.Commit() + 0x285 bytes  
Microsoft.PowerShell.GPowerShell.dll!Microsoft.PowerShell.Host.ISE.PowerShellTab.TabComplete(Microsoft.PowerShell.Host.ISE.ISEEditor editor, bool forward) + 0x51c bytes  
Microsoft.PowerShell.GPowerShell.dll!Microsoft.PowerShell.Host.ISE.PowerShellTab.ProcessTab(object sender, System.Windows.Input.KeyEventArgs e, Microsoft.PowerShell.Host.ISE.PowerShellTab selectedPowerShellTab) + 0x167 bytes  
Microsoft.PowerShell.GPowerShell.dll!Microsoft.Windows.PowerShell.Gui.Internal.BeforeDefaultKeyProcessor.KeyDown(System.Windows.Input.KeyEventArgs args) + 0x4a bytes 
Microsoft.PowerShell.Editor.dll!Microsoft.VisualStudio.Text.Utilities.GuardedOperations.CallExtensionPoint(object errorSource, System.Action call) + 0x26 bytes 
Microsoft.PowerShell.Editor.dll!Microsoft.VisualStudio.Text.Editor.Implementation.KeyProcessorDispatcher.Dispatch<System.Windows.Input.KeyEventArgs>(System.Action<Microsoft.VisualStudio.Text.Editor.KeyProcessor,System.Windows.Input.KeyEventArgs> action, System.Windows.Input.KeyEventArgs args) + 0x185 bytes 
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) + 0x56 bytes 
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) + 0x270 bytes 
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) + 0x14e bytes 
PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args) + 0x64 bytes 
PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() + 0x431 bytes 
PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) + 0xab bytes 
PresentationCore.dll!System.Windows.Interop.HwndKeyboardInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawKeyboardActions actions, int scanCode, bool isExtendedKey, bool isSystemKey, int virtualKey) + 0x124 bytes  
PresentationCore.dll!System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(ref System.Windows.Interop.MSG msg, ref bool handled) + 0x20e bytes 
PresentationCore.dll!System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(ref System.Windows.Interop.MSG msg, System.Windows.Input.ModifierKeys modifiers) + 0x213 bytes 
PresentationCore.dll!System.Windows.Interop.HwndSource.OnPreprocessMessage(object param) + 0x35e bytes 
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x5e bytes 
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) + 0x47 bytes  
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) + 0x2bc bytes 
WindowsBase.dll!System.Windows.Threading.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority priority, System.Delegate method, object arg) + 0x42 bytes 
PresentationCore.dll!System.Windows.Interop.HwndSource.OnPreprocessMessageThunk(ref System.Windows.Interop.MSG msg, ref bool handled) + 0x107 bytes 
WindowsBase.dll!System.Windows.Interop.ComponentDispatcherThread.RaiseThreadMessage(ref System.Windows.Interop.MSG msg) + 0x4f bytes  
WindowsBase.dll!System.Windows.Threading.Dispatcher.TranslateAndDispatchMessage(ref System.Windows.Interop.MSG msg) + 0x2c bytes  
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0x112 bytes 
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x17a bytes  
Microsoft.PowerShell.GPowerShell.dll!Microsoft.Windows.PowerShell.Gui.Internal.Program.ShowMainWindow(System.Collections.Generic.List<string> filesToOpen, bool mta, bool noProfile, System.Threading.SendOrPostCallback loadedCallback) + 0x1a5 bytes 
[Native to Managed Transition] 
PowerShell_ISE.exe!Microsoft.Windows.PowerShell.GuiExe.Internal.GPowerShell.Main(string[] args) + 0x4d0 bytes 

我只包括了線之間的部分的一個重複:

mscorlib.dll!System.Resources.ResourceManager.GetString(string name, System.Globalization.CultureInfo culture) + 0x23c bytes 

但重複了很多。

我已經通過洗衣機幾次,我並不總是在調用堆棧中看到相同的結果。例如,有時在重複部分看起來像這樣:

mscorlib.dll!System.Resources.ResourceManager.GetString(string name, System.Globalization.CultureInfo culture) + 0x23c bytes  
System.Management.Automation.dll!System.Management.Automation.ErrorCategoryInfo.Ellipsize(System.Globalization.CultureInfo uiCultureInfo, string original) + 0x88 bytes 
System.Management.Automation.dll!System.Management.Automation.ScriptBlock.InvokeAsDelegateHelper(object dollarUnder, object dollarThis, object[] args) + 0x137 bytes  
[Lightweight Function] 
mscorlib.dll!System.AppDomain.OnAssemblyResolveEvent(System.Reflection.RuntimeAssembly assembly, string assemblyFullName) + 0xbc bytes 
[Native to Managed Transition] 
[Managed to Native Transition] 
mscorlib.dll!System.Reflection.RuntimeAssembly.InternalGetSatelliteAssembly(string name, System.Globalization.CultureInfo culture, System.Version version, bool throwOnFileNotFound, ref System.Threading.StackCrawlMark stackMark) + 0x3ab bytes 
mscorlib.dll!System.Resources.ManifestBasedResourceGroveler.GetSatelliteAssembly(System.Globalization.CultureInfo lookForCulture, ref System.Threading.StackCrawlMark stackMark) + 0xdd bytes 
mscorlib.dll!System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(System.Globalization.CultureInfo culture, System.Collections.Generic.Dictionary<string,System.Resources.ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists, ref System.Threading.StackCrawlMark stackMark) + 0xe2 bytes 
mscorlib.dll!System.Resources.ResourceManager.InternalGetResourceSet(System.Globalization.CultureInfo requestedCulture, bool createIfNotExists, bool tryParents, ref System.Threading.StackCrawlMark stackMark) + 0x329 bytes 
mscorlib.dll!System.Resources.ResourceManager.InternalGetResourceSet(System.Globalization.CultureInfo culture, bool createIfNotExists, bool tryParents) + 0x23 bytes  
mscorlib.dll!System.Resources.ResourceManager.GetString(string name, System.Globalization.CultureInfo culture) + 0x23c bytes  

,而重複開始前的初始部分是往往不同。

從閱讀的一小段看來,LightweightFunction可能是我的函數Resolve-AssemblyRedirect。

我做錯了什麼?

+0

我似乎能夠通過簡單地註冊一個解析器和呼喚-的GridView到REPRO此:$ OnAssemblyResolve = \t \t [System.ResolveEventHandler] { \t \t PARAM($發件人,$ resolveEventArgs) 返回null; } [System.AppDomain] :: CurrentDomain.add_AssemblyResolve($ OnAssemblyResolve); 1..10 | out-gridview –

回答

3

沒有深入研究AppDomain程序集解析的東西,我可以告訴你,最有可能在堆棧遍歷中的重複行代表的代碼路徑中存在非終止循環。每次代碼通過循環時,它會消耗更多堆棧,直到所有堆棧都被使用,並且獲得與本網站同名的異常。

我的猜測是,您對.config文件所做的更改會導致.NET表現不佳。

使用反射器我可以看到無限循環。 InvokeAsDelegateHelper調用GetContextFromTLS。 GetContextFromTLS調用GetExecutionContextFromTLS。如果DefaultRunspace爲空,GetExecutionContextFromTLS將返回null。當GetContextFromTLS從GetExecutionContextFromTLS(除別的以外)得到一個null後,它調用ErrorCategory.Ellipsize。 Ellipsize讀取屬性ErrorPackage.Ellipsize。 ErrorPackage.Ellipsize訪問器方法調用ResourceManager.GetString,它重新啓動循環

因此,看起來不良行爲來自具有空DefaultRunspace。我不確定如果您只是使用Powershell.exe來運行腳本,情況會如何。但是,如果您從C#調用Powershell,那麼您的代碼中可能會有一個調用Powershell的錯誤。無論哪種方式,在關於從程序啓動Powershell的文檔中查看MSDN可能會很有幫助。

HTH

+0

謝謝。我正在使用PowerShell ISE。我要複製一個乾淨的.config文件,看看我是否可以重新創建它。 – Simon

+0

它不是.config文件。我在另一臺機器上使用無損的.config文件重新創建了該問題。 – Simon

+0

關鍵因素是DefaultRunspace爲空。也許腳本運行在未設置運行Powershell的線程上。 「TLS」表示線程本地存儲。你可以在腳本中添加一些邏輯來輸出它正在運行的線程('[threading.thread] :: CurrentThread'),看看它是否與執行Powershell的線程相同。或者嘗試使用-STA命令行選項運行PS。祝你好運 –

相關問題