Link to home
Create AccountLog in
Avatar of Tinman0330
Tinman0330

asked on

Passing Keys without focus

Visual Basic 2008
SendMessage API

Hello All,

    I am trying to make a program that can inject Keys and commands into a program that does not have focus. It no longer screams at me about Overflows and Unbalanced stack, but there is a new problem. It does nothing at all. There are no errors and there are no results.
I have tried sending with WM_KEYDOWN, WM_KEYUP.
I have tried sending with WM_CHAR
I have tried to just minimize the program.
None of these have worked. I think I have the wrong Handle or something. In the past I have used FindWindow API to get the HWND (VB6)  but now I can't because I get an overflow when sending it using SendMessage.  I have tried to pass a number key into NOTEPAD, CALC, and a game that gave me an Access Denied message <<< not cool>>>.  Well, that's what is going on. I started a new program with just the basic code needed so that I could post it here.

Question 1.  How do I get it to actually send a key stroke/command without focus?
Question 2. (Optional) How can I pass keys/commands to an "Access denied"  process that is not a system process?

BTW     SendMessage inside of a TRY Catch    is a bad idea!    That one took a while.
Thanks in advance =D

'******************
'Listbox1 (List of Processes)
'Button1  (Send the number 8 to the process)
'Button2  (Refresh process list)
'******************
 
Public Class Form1
    Dim ProcessList() As Process
 
    Private Const VK_8 As Integer = 38
    Private Const WM_KEYDOWN = &H100
    Private Const WM_KEYUP = &H101
 
    Declare Auto Function SendMessage Lib "user32.dll" ( _
        ByVal hWnd As IntPtr, ByVal Msg As Integer, _
        ByVal wParam As Integer, ByRef lParam As IntPtr _
        ) As Integer
 
    Private Sub GetProcesses()
        Dim X As Long
        ListBox1.Items.Clear()
        ProcessList = Process.GetProcesses
        For X = 0 To UBound(ProcessList) - 1
            Application.DoEvents()
            ListBox1.Items.Add(ProcessList(X).ProcessName)
        Next
    End Sub
 
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        GetProcesses()
    End Sub
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim HWND As Long
        HWND = ProcessList(ListBox1.SelectedIndex).Handle
        SendMessage(HWND, WM_KEYDOWN, VK_8, IntPtr.Zero)
        SendMessage(HWND, WM_KEYUP, VK_8, IntPtr.Zero)
    End Sub
 
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        GetProcesses()
    End Sub
End Class

Open in new window

Avatar of Zoppo
Zoppo
Flag of Germany image

Hi Tinman0330,

I'm not very familiar with VB but as far as I see you send a window message to a handle which is a process-handle, not a window handle. Try using 'Process::MainWindowHandle' instead, but you should first check if that handle isn't NULL before sending a message.

Hope that helps,

ZOPPO
Avatar of Tinman0330
Tinman0330

ASKER

I changed
     HWND = ProcessList(ListBox1.SelectedIndex).Handle
to
     HWND = ProcessList(ListBox1.SelectedIndex).MainWindowHandle

Still have the same problem. I tested it with Calculator and notepad. Thank you for the fast response =)
Haven't studied it too closely but you should not be using a Long to hold the Handle either...

Change:

    Dim HWND As Long
    HWND = ProcessList(ListBox1.SelectedIndex).Handle

To:

    Dim HWND As IntPtr
    HWND = ProcessList(ListBox1.SelectedIndex).MainWindowHandle

oops I missed that one =)
Changed
     Dim HWND As Long
To
     Dim HWND As IntPtr

Also used .Handle and .Mainwindowhandle  method.
Tested with Calculator and notepad. Same results =(
ASKER CERTIFIED SOLUTION
Avatar of Zoppo
Zoppo
Flag of Germany image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Made all of the changes and posted new code.
So Far it works with the following:
     Calculator
     Excel
     Cmd <Prompt>

Does not work with:
     Notepad
     Wordpad
     MS Word
     Defcon game

Could the message me denied somehow?
Public Class Form1
    Dim ProcessList() As Process
 
    Private Const VK_8 As Integer = &H38
    Private Const WM_KEYDOWN = &H100
    Private Const WM_KEYUP = &H101
    Private Const WM_CHAR As Integer = &H102
    Declare Auto Function SendMessage Lib "user32.dll" ( _
        ByVal hWnd As IntPtr, ByVal Msg As Integer, _
        ByVal wParam As Integer, ByRef lParam As IntPtr _
        ) As Integer
 
    Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" ( _
        ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr _
        ) As Long
 
    Private Sub GetProcesses()
        Dim X As Long
        ListBox1.Items.Clear()
        ProcessList = Process.GetProcesses
        For X = 0 To UBound(ProcessList) - 1
            Application.DoEvents()
            ListBox1.Items.Add(ProcessList(X).ProcessName)
        Next
    End Sub
 
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        GetProcesses()
    End Sub
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim HWND As IntPtr
        HWND = ProcessList(ListBox1.SelectedIndex).MainWindowHandle
        'SendMessage(HWND, WM_KEYDOWN, VK_8, IntPtr.Zero)
        'SendMessage(HWND, WM_KEYUP, VK_8, IntPtr.Zero)
        PostMessage(HWND, WM_CHAR, VK_8, IntPtr.Zero)
    End Sub
 
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        GetProcesses()
    End Sub
End Class

Open in new window

Hi again,

well, that's a problem: If an application doesn't handle the WM_CHAR message but does handle WM_KEYDOWN/WM_KEYUP your code will fail ... a WM_CHAR message is AFAIK produced by the application itself while handling WM_KEYDOWN/WM_KEYUP - but there's no guarantee that the application really does this - it could even just rely on the WM_KEYDOWN/WM_KEYUP message without generating a WM_CHAR message.

ZOPPO
So far the Keyup/Down and WM_CHAR have both worked or both failed. What is the difference between my program sending a window a Keypress message and the OS sending the same window a keypress when I hit a key on my keyboard. What API alerts the window of a keypress when I use my keyboard? Is there a way to detect the last focused object in a window and send the message to the object? Maybe there is a problem sending keystrokes to a window that has multiple objects that could have focus. If that is the case I don't know why it would work in excel.......I'm a little confused =/    I would think that it would work for all or none.  So what is the difference between using postmessage and hitting a key on my keyboard other than focus?
Hi,

well, I think the OS sends a WM_KEYDOWN/WM_KEYUP message to that window which has the focus - this indeed may be a different window than the application's main window. A WM_CHAR message is AFAIK generated by the application itself (or better said by the WM_KEYDOWN/WM_KEYUP handling function of thw window which recieves the message or the parent windows or the application) in case it recieved a WM_KEYDOWN/WM_KEYUP which is interpreted to be treated as a entered char. But an application can even directly interpret the WM_KEYDOW/WM_KEYUP without need to generate a WM_CHAR message.

>  I would think that it would work for all or none
So, it's never guaranteed that an application handles WM_CHAR messages, and it's not guaranteed that the application's main window handles WM_KEYDOWN/WM_KEYUP messages the same way as the window which had focus when the application was active.

Unfortunateley I fear it's not possible to find the info which window of another process had focus before the application was de-activated.

ZOPPO
You seem to know way more on this subject than I do =)  

At this link there is a person who claims to have the same problem in notepad/wordpad/etc but does not have that problem when passing the shift key...... I may have read it wrong, what do you think?

http://www.vbforums.com/showthread.php?t=303826