我正在 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/