调用tab-completion / Intellisense时PowerShell中的StackOverflowException

时间:2013-12-10 11:27:27

标签: powershell stack-overflow assembly-resolution powershell-ise

我正在PowerShell中编写一个PowerShell模块,它必须重定向程序集绑定。 我在bindingRedirect中使用powershell_ise.exe.config时没有遇到任何问题,但我不认为这对于我想要分发的模块是可以接受的,所以我寻找其他方式并遇到AppDomain.CurrentDomain.AssemblyResolve

我目前正在.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
}

我可以通过在ISE中使用tab-completion / Intellisense来相当可靠地触发问题。我也在shell中看到过它。当我说得相当可靠时,它并不总是触发它的cmdlet。例如,在准备这个时,我用Get-ADUser [tab]触发了它,最近,我输入了get-por [tab],Intellisense显示了Get-GPOReport然后它挂了。

如果我注释掉[AppDomain] ::开头的那一行,并且没有看到问题。

在我继续之前,我想指出我以前从未在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。

我做错了吗?

1 个答案:

答案 0 :(得分:3)

在不深入研究AppDomain程序集解析的情况下,我可以告诉你,很可能在堆栈遍历中的重复行所代表的代码路径中存在非终止循环。每次代码通过循环时,它会占用更多堆栈,直到所有堆栈都被使用,并且您获得与此网站同名的异常。

我的猜测是你对.config文件所做的更改导致.NET表现不佳。

使用反射器我可以看到无限循环。 InvokeAsDelegateHelper调用GetContextFromTLS。 GetContextFromTLS调用GetExecutionContextFromTLS。如果DefaultRunspace为null,则GetExecutionContextFromTLS返回null。当GetContextFromTLS从GetExecutionContextFromTLS(以及其他内容)获取空值时,它调用ErrorCategory.Ellipsize。 Ellipsize读取属性ErrorPackage.Ellipsize。 ErrorPackage.Ellipsize访问器方法调用ResourceManager.GetString,它重新启动循环

所以看起来坏行为来自于具有null的DefaultRunspace。如果您只是使用Powershell.exe来运行脚本,我不确定会发生什么情况。但是如果你从C#调用Powershell,那么你的代码中可能会有一个调用Powershell的错误。无论哪种方式,在有关从程序启动Powershell的文档中查看MSDN可能会有所帮助。

HTH