Kushal
Kushal

Reputation: 3168

PInvokeStackImbalance when using GetAsyncKeyState in VB.NET 2010

What I'm trying to do is tracing Ctrl+Tab keypress on my main form using following code

<DllImport("user32.dll", PreserveSig:=False)>
Private Shared Function GetAsyncKeyState(ByVal vKey As System.Windows.Forms.Keys) As Short
End Function

Private ReadOnly Property CtrlPressed As Boolean
    Get
        Dim keyval As Integer
        keyval = GetAsyncKeyState(Keys.ControlKey)
        If keyval = 0 Then
            CtrlPressed = False
        Else
            CtrlPressed = True
        End If
    End Get
End Property

But while calling the property CtrlPressed I'm getting PInvokeStackImbalance error. I'm sure with declaration of GetAsyncKeyState and also have imported InteropServices but the CtrlPressed property has something syntactically wrong. How can I solve this issue?

Thanks

Upvotes: 0

Views: 2047

Answers (1)

Cody Gray
Cody Gray

Reputation: 244752

A stack imbalance error almost always means that your P/Invoke definition signature is wrong. The first thing to do is check carefully all of your types and make sure that they match the documented signature for the native function. In this case, it looks good.

Except that you've set PreserveSig to False, and I'm not really sure why. As the documentation for that field indicates, it is designed for use with unmanaged methods that return an error code (for example, an HRESULT code). It instructs the runtime to automatically convert those error codes into exceptions. But the GetAsyncKeyState method doesn't return an error code, so enabling this option doesn't make a lot of sense.

The following code works fine for me:

<DllImport("user32.dll")> _
Private Shared Function GetAsyncKeyState(ByVal vKey As Keys) As Short
End Function

Private ReadOnly Property IsCtrlPressed As Boolean
    Get
        Dim isPressed As Short = GetAsyncKeyState(Keys.ControlKey)
        Return (isPressed & &H8000) != 0
    End Get
End Property

Make sure that you've paid close attention to the documentation for the GetAsyncKeyState function. Specifically, the section on return values:

If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState. However, you should not rely on this last behavior; for more information, see the Remarks.

The return value is zero for the following cases:

  • The current desktop is not the active desktop
  • The foreground thread belongs to another process and the desktop does not allow the hook or the journal record.

Upvotes: 1

Related Questions