1

我正在使用此功能从低级键盘挂钩中查找击键...

Const UnicodeBufferExSize As Integer = 64
Public Declare Function ToUnicodeEx Lib "user32" (wVirtKey As UInteger,
    wScanCode As UInteger,
    lpKeyState As Byte(),
    <Out()>
    <MarshalAs(UnmanagedType.LPWStr, SizeConst:=UnicodeBufferExSize)> '<-- Note this line (#A)
    ByVal lpChar As System.Text.StringBuilder,
    cchBuff As Integer,
    wFlags As UInteger,
    dwhkl As IntPtr) As Integer

...

Dim SB As New System.Text.StringBuilder(UnicodeBufferExSize) '<-- And this one (#B)

ToUnicodeEx(CUInt(lParam.vkCode),
            CUInt(lParam.scanCode),
            KeyState,
            SB,
            SB.Capacity, '<-- And this (#C)
            0,
            InputLanguage.CurrentInputLanguage.Handle)

GC.Collect()
Return SB.ToString()

对ToUnicodeEx的调用采用一个参数,该参数指示StringBuilder要填充的缓冲区的大小(第 #C 行)。

如果我创建一个StringBuilder没有容量参数(第 #B 行,当前实现似乎默认为反射的容量为 16)并省略SizeConst(第 #A 行),则调用通常会成功,但有时会导致托管堆损坏异常。

现在,我添加了UnicodeBufferExSize常量,希望能够解决问题,并且似乎已经这样做了 - 但我不知道它是否真的修复了它,或者只是让它变得更加罕见。

有人可以解释为什么简单地传入缓冲区大小是不够的吗?并确认我的解决方案是否正确或是否有任何细微的错误?

(请注意,调用GC.Collect()会更快地触发问题,并且仅用于帮助调试。)

继汉斯(Hans)的(第一)评论之后......

在此处输入图像描述

Problem signature:
  Problem Event Name:   APPCRASH
  Application Name: Glue.exe
  Application Version:  3.1.3.0
  Application Timestamp:    52001dc3
  Fault Module Name:    ntdll.dll
  Fault Module Version: 6.1.7601.17725
  Fault Module Timestamp:   4ec4aa8e
  Exception Code:   c0000005
  Exception Offset: 00000000000532d0
  OS Version:   6.1.7601.2.1.0.256.1
  Locale ID:    2057
  Additional Information 1: 355b
  Additional Information 2: 355bc389704a5d6b4e279d0f0bd3355a
  Additional Information 3: 02ad
  Additional Information 4: 02ad05628a0a65c888b4805dfd9c6b58
4

0 回答 0