Powershell 中的内部 CLR 错误 (0x80131506) 和崩溃
Internal CLR errors (0x80131506) and crash in Powershell
首先我要说错误的原因本身实际上可能与 PowerShell 具体无关,它可能更深层次地存在于 .NET 中,但这正是我遇到它的地方。
PowerShell 版本:7.1.0
我定义了以下类型以解析资源请求,例如在注册表中使用的(签名与 PInvoke.net 上看到的完全一样):
Add-Type -TypeDefinition @"
using System;
using System.Text;
using System.Runtime.InteropServices;
public static class ShellHelper {
[DllImport("shlwapi.dll", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false, ThrowOnUnmappableChar = true)]
public static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, int cchOutBuf, IntPtr ppvReserved);
}
"@
现在对于测试用例,请考虑以下内容:
$result = [System.Text.StringBuilder]::New();
$tmp = [System.IntPtr]::New(0);
[ShellHelper]::SHLoadIndirectString("@firewallapi.dll,-50323", $result, 256, $tmp) > $null;
$result.ToString()
输出 SNMP Trap
已生成,一切看起来都不错。其他一些值也可以正常工作。但是,例如,如果我用 -50326
替换数字 -50323
那么我仍然会得到 Block any other traffic to and from SNMPTRAP service
的正确值作为输出,但是在我采取的几乎所有操作(即执行命令,甚至只是按 Tab)就会抛出一系列无休止的 Fatal error. Internal CLR error. (0x80131506)
异常,直到我收到 Stack overflow.
消息并且 PowerShell 崩溃到桌面。 (参见 https://imgur.com/a/MYZwhYa。)
错误取决于正在处理的字符串,而不是到目前为止方法调用的数量:如果在新会话中首先调用最后一个命令,则会立即发生相同的错误。
除了输出字符串可能的某些属性(它的长度、某些字符的存在等)之外,我一直无法确定甚至无法合理猜测到底是什么导致了这种行为。使用某些参数(更改第三个参数,使用 out int
和 [ref]
作为第四个参数等)似乎不会影响结果。
我主要是被错误的奇怪时间弄糊涂了。似乎某些内部进程可能会导致内存中的其他数据损坏,从而导致以后出现错误,但这只是我的猜测。我也可能只是遗漏了一些非常明显的东西。
造成这种行为的原因可能是什么?如果它是 .NET 中的一个真正的错误,我怎么可能解决它,或者甚至只是着手确定它发生的确切标准?
像您一样使用 StringBuilder
构造函数,传递 0 或不传递任何内容,您有效地为其提供了 16 个字符的容量(默认容量)。您可以通过在 New
之后添加 $result.Capacity
来验证这一点。
当您随后调用 SHLoadIndirectString
时,您将 256
作为大小传递,因此该函数假定它可以将那么多字节写入 result
缓冲区。它这样做,因为它现在有办法知道 $result
实际上只能占用 16 个字节,因此会覆盖 PowerShell 进程中的其他任意内存。
内存损坏错误通常不会在您实际损坏内存时导致崩溃,但在以后的任何时候都不会。
您需要传递实际可用的尺寸,如下所示:
$result = [System.Text.StringBuilder]::New(256);
$tmp = [System.IntPtr]::New(0);
[ShellHelper]::SHLoadIndirectString("@firewallapi.dll,-50323", $result, $result.Capacity, $tmp) > $null;
$result.ToString()
首先我要说错误的原因本身实际上可能与 PowerShell 具体无关,它可能更深层次地存在于 .NET 中,但这正是我遇到它的地方。
PowerShell 版本:7.1.0
我定义了以下类型以解析资源请求,例如在注册表中使用的(签名与 PInvoke.net 上看到的完全一样):
Add-Type -TypeDefinition @"
using System;
using System.Text;
using System.Runtime.InteropServices;
public static class ShellHelper {
[DllImport("shlwapi.dll", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false, ThrowOnUnmappableChar = true)]
public static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, int cchOutBuf, IntPtr ppvReserved);
}
"@
现在对于测试用例,请考虑以下内容:
$result = [System.Text.StringBuilder]::New();
$tmp = [System.IntPtr]::New(0);
[ShellHelper]::SHLoadIndirectString("@firewallapi.dll,-50323", $result, 256, $tmp) > $null;
$result.ToString()
输出 SNMP Trap
已生成,一切看起来都不错。其他一些值也可以正常工作。但是,例如,如果我用 -50326
替换数字 -50323
那么我仍然会得到 Block any other traffic to and from SNMPTRAP service
的正确值作为输出,但是在我采取的几乎所有操作(即执行命令,甚至只是按 Tab)就会抛出一系列无休止的 Fatal error. Internal CLR error. (0x80131506)
异常,直到我收到 Stack overflow.
消息并且 PowerShell 崩溃到桌面。 (参见 https://imgur.com/a/MYZwhYa。)
错误取决于正在处理的字符串,而不是到目前为止方法调用的数量:如果在新会话中首先调用最后一个命令,则会立即发生相同的错误。
除了输出字符串可能的某些属性(它的长度、某些字符的存在等)之外,我一直无法确定甚至无法合理猜测到底是什么导致了这种行为。使用某些参数(更改第三个参数,使用 out int
和 [ref]
作为第四个参数等)似乎不会影响结果。
我主要是被错误的奇怪时间弄糊涂了。似乎某些内部进程可能会导致内存中的其他数据损坏,从而导致以后出现错误,但这只是我的猜测。我也可能只是遗漏了一些非常明显的东西。
造成这种行为的原因可能是什么?如果它是 .NET 中的一个真正的错误,我怎么可能解决它,或者甚至只是着手确定它发生的确切标准?
像您一样使用 StringBuilder
构造函数,传递 0 或不传递任何内容,您有效地为其提供了 16 个字符的容量(默认容量)。您可以通过在 New
之后添加 $result.Capacity
来验证这一点。
当您随后调用 SHLoadIndirectString
时,您将 256
作为大小传递,因此该函数假定它可以将那么多字节写入 result
缓冲区。它这样做,因为它现在有办法知道 $result
实际上只能占用 16 个字节,因此会覆盖 PowerShell 进程中的其他任意内存。
内存损坏错误通常不会在您实际损坏内存时导致崩溃,但在以后的任何时候都不会。
您需要传递实际可用的尺寸,如下所示:
$result = [System.Text.StringBuilder]::New(256);
$tmp = [System.IntPtr]::New(0);
[ShellHelper]::SHLoadIndirectString("@firewallapi.dll,-50323", $result, $result.Capacity, $tmp) > $null;
$result.ToString()