powershell - 调用制表符补全/Intellisense 时 PowerShell 中出现 StackOverflowException

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

我正在 PowerShell 中编写一个 PowerShell 模块,它必须重定向程序集绑定(bind)。 我在 powershell_ise.exe.config 中使用 bindingRedirect 没有任何问题,但我认为这对于我想要分发的模块来说是 Not Acceptable ,所以我寻找其他方法并遇到了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 中使用制表符完成/智能感知,我可以相当可靠地触发该问题。我也在shell中看到过。当我说相当可靠时,触发它的并不总是同一个 cmdlet。例如,在准备此过程中,我使用 Get-ADUser [tab] 触发了它,最近,我输入了 get-por [tab],Intellisense 显示了 Get-GPOReport,然后它挂起了。

如果我注释掉以 [AppDomain]::开头的行,并使用制表符完成,我不会发现问题。

在继续之前,我想指出,我以前从未在 PowerShell 中调试过任何内容,因此在黑暗中摸索了很多。为了进行调试,我在 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug 中添加了一个 REG_SZ,其名称为 Auto ,其值1,它为我提供了启动 VS 2012 的选项。然后向我显示:

System.StackOverflowException was unhandled

当我查看调用堆栈时,我看到:

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。

我做错了什么吗?

最佳答案

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

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

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

所以看起来不良行为来自于具有空的 DefaultRunspace。我不确定如果您只是使用 Powershell.exe 运行脚本,会发生什么情况。但是,如果您从 C# 等方式调用 Powershell,那么您的代码中可能存在调用 Powershell 的错误。不管怎样,在 MSDN 上查看有关从程序启动 Powershell 的文档可能会有所帮助。

HTH

关于powershell - 调用制表符补全/Intellisense 时 PowerShell 中出现 StackOverflowException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20493245/

相关文章:

powershell - 使用Powershell评估负数

powershell - 了解用于添加受信任的UCMA 4.0应用程序和受信任的UCMA 4.0应用程序终结点的PowerShell cmdlet

fortran - Fortran程序中的堆栈溢出

将 ArrayList 放入 HashMap 后出现 Java StackOverflowError

c# - AssemblyName.ReferenceMatchesDefinition 如何工作?

powershell - 我正在尝试编写将两个WMI命令结合在一起的PowerShell脚本

powershell - 将测试连接转换为 bool 值

C 运行时计算器

c# - 加载任何版本的静态引用 .NET 程序集

asp.net - 如何在ASP.net应用程序的bin文件夹之外引用程序集?