הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
Question
Tuesday, November 15, 2016 8:45 AM
Hi ,
So in the beginning of this, We all know SendKey Method does send a key the active process, Of course we can send a key to a specific process after we activate it and then SendKey,
However, we're not talking about that, we want to send a key (char, not message), to the specified process without activating it via hooking,
This is actually a little bit complicated for me, so i searched google and found this helpful question similar to this but in C#
This answer was helpful and enough, but can we do it in VB.NET ?"
Regards.
All replies (33)
Tuesday, November 15, 2016 9:31 AM
This answer was helpful and enough, but can we do it in VB.NET ?
Most of the code is .Net framework methods and classes. so the language used doesn't much matter. If it can be done in C# then it almost certainly can be done in VB. You can convert that code using a code converter, such as:
Code Converter
Tuesday, November 15, 2016 10:36 PM
Hi ,
So in the beginning of this, We all know SendKey Method does send a key the active process, Of course we can send a key to a specific process after we activate it and then SendKey,
However, we're not talking about that, we want to send a key (char, not message), to the specified process without activating it via hooking,
This is actually a little bit complicated for me, so i searched google and found this helpful question similar to this but in C#
This answer was helpful and enough, but can we do it in VB.NET ?"
Regards.
I believe SendKeys sends a keystroke to an active window. For example if Notepad is the active process and its edit window is the active window of the active process then SendKeys would send the keystrokes to the edit window and not somewhere else in Notepad.
La vida loca
Wednesday, November 16, 2016 11:42 AM
This answer was helpful and enough, but can we do it in VB.NET ?
Most of the code is .Net framework methods and classes. so the language used doesn't much matter. If it can be done in C# then it almost certainly can be done in VB. You can convert that code using a code converter, such as:
Code Converter
I tried but already the code has a problem , when i call the function using:
sendKeystroke(Keys.A);
It Says that sendKeystroke(ushort) has some invalid arguments (At the Calling Line) , i saw that ushort does accept int only :|
Any help with that ?
Wednesday, November 16, 2016 11:53 AM
I believe SendKeys sends a keystroke to an active window. For example if Notepad is the active process and its edit window is the active window of the active process then SendKeys would send the keystrokes to the edit window and not somewhere else in Notepad.
Well, what i want is just sending the key to the process not to something specified in the process.
Plus it is a background process, so that is a little bit complicated to send a key to non-active process
Wednesday, November 16, 2016 12:19 PM
I tried but already the code has a problem , when i call the function using:
sendKeystroke(Keys.A);
It Says that sendKeystroke(ushort) has some invalid arguments (At the Calling Line) , i saw that ushort does accept int only :|
What is the function definition? That error message indicates that the Type of Keys.A is not what the function is expecting as an argument. The Type of an enumeration is Integer.
https://msdn.microsoft.com/en-us/library/system.windows.forms.keys%28v=vs.110%29.aspx
Wednesday, November 16, 2016 12:20 PM
Please show the VB code you have now.
You can not send a key to a process. You can only send it to a specific window. Windows is message based, and messages are sent to windows.
Armin
Wednesday, November 16, 2016 12:40 PM
What is the function definition? That error message indicates that the Type of Keys.A is not what the function is expecting as an argument. The Type of an enumeration is Integer.
https://msdn.microsoft.com/en-us/library/system.windows.forms.keys%28v=vs.110%29.aspx
I know what it means :|
but he said in his replay the calling line contains (Keys.A), is he mistaken or ?...
Wednesday, November 16, 2016 12:45 PM
Please show the VB code you have now.
You can not send a key to a process. You can only send it to a specific window. Windows is message based, and messages are sent to windows.
Well , Acamar suggested to convert the code from C# to VB, this was the result:
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("user32.dll")> _
Public Shared Function FindWindow(lpClassName As String, lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll")> _
Public Shared Function SendMessage(hWnd As IntPtr, Msg As UInteger, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
<DllImport("user32.dll")> _
Public Shared Function PostMessage(hWnd As IntPtr, Msg As UInteger, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
Public Shared Sub sendKeystroke(k As UShort)
Const WM_KEYDOWN As UInteger = &H100
Const WM_SYSCOMMAND As UInteger = &H18
Const SC_CLOSE As UInteger = &H53
Dim WindowToFind As IntPtr = FindWindow(Nothing, "WindowName")
Dim result3 As IntPtr = SendMessage(WindowToFind, WM_KEYDOWN, DirectCast(k, IntPtr), DirectCast(0, IntPtr))
'IntPtr result3 = SendMessage(WindowToFind, WM_KEYUP, ((IntPtr)c), (IntPtr)0);
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
sendKeystroke(Keys.A)
End Sub
End Class
and there is an error at line 22 ,
Dim result3 As IntPtr = SendMessage(WindowToFind, WM_KEYDOWN, DirectCast(k, IntPtr), DirectCast(0, IntPtr))
Wednesday, November 16, 2016 1:06 PM
What is the exception (error)?
Paul ~~~~ Microsoft MVP (Visual Basic)
Wednesday, November 16, 2016 1:19 PM
What is the exception (error)?
Error 1 Value of type 'UShort' cannot be converted to 'System.IntPtr'. Ln:22 Ch:82
Error 2 Value of type 'Integer' cannot be converted to 'System.IntPtr'. Ln:22 Ch:105
Wednesday, November 16, 2016 2:08 PM
What is the exception (error)?
Error 1 Value of type 'UShort' cannot be converted to 'System.IntPtr'. Ln:22 Ch:82
Error 2 Value of type 'Integer' cannot be converted to 'System.IntPtr'. Ln:22 Ch:105
I don't know anything about the app you are trying to send messages to, but this works for me:
<DllImport("user32.dll", EntryPoint:="FindWindowEx")>
Public Shared Function FindWindowEx(ByVal hwndParent As IntPtr, ByVal hwndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
End Function
<DllImport("User32.dll")>
Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
End Function
Private Sub SendMessageToNotepad()
Dim notepads() As Process = Process.GetProcessesByName("notepad")
If notepads.Length = 0 Then
Return
End If
If notepads(0) IsNot Nothing Then
Dim child As IntPtr = FindWindowEx(notepads(0).MainWindowHandle, New IntPtr(0), "Edit", Nothing)
SendMessage(child, &HC, 0, "This is a test")
End If
End Sub
Paul ~~~~ Microsoft MVP (Visual Basic)
Wednesday, November 16, 2016 4:52 PM | 1 vote
You can sent anything you want to whatever place you want.
But as the other one has no way to accept it, it is a waste of time.
Success
Cor
Wednesday, November 16, 2016 8:21 PM
Well , Acamar suggested to convert the code from C# to VB, this was the result:
That code is for sending a message to a window. It is not good enough for communicating with a background process that does not have a window. You need to search for some better example.
Wednesday, November 16, 2016 9:49 PM
I don't know anything about the app you are trying to send messages to, but this works for me:
<DllImport("user32.dll", EntryPoint:="FindWindowEx")> Public Shared Function FindWindowEx(ByVal hwndParent As IntPtr, ByVal hwndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr End Function <DllImport("User32.dll")> Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer End Function Private Sub SendMessageToNotepad() Dim notepads() As Process = Process.GetProcessesByName("notepad") If notepads.Length = 0 Then Return End If If notepads(0) IsNot Nothing Then Dim child As IntPtr = FindWindowEx(notepads(0).MainWindowHandle, New IntPtr(0), "Edit", Nothing) SendMessage(child, &HC, 0, "This is a test") End If End Sub
I tried that code, but it does send messages , not key strokes , right ?"
Like sending F1 to the Notepad, can you ?"
Wednesday, November 16, 2016 9:50 PM
You can sent anything you want to whatever place you want.
But as the other one has no way to accept it, it is a waste of time.
Well, it have a way to accept it but it's not almost likely to Notepad.
Wednesday, November 16, 2016 10:01 PM
I tried that code, but it does send messages , not key strokes , right ?"
Like sending F1 to the Notepad, can you ?"
Key strokes are messages. The example doesn't send a key stroke but it sends a text. &HC is WM_SETTEXT .
In your code, instead of using DirectCast, use "New IntPtr(value)"
Armin
Wednesday, November 16, 2016 10:18 PM
That code is for sending a message to a window. It is not good enough for communicating with a background process that does not have a window. You need to search for some better example.
You are actually right,,
But after thinking about the example, if it is a window like Notepad and i want to send text to it then i need to get the handle of the "Edit" child window, but how can i do it on other process without a specific child window? just like SendKey Method ?
Wednesday, November 16, 2016 10:23 PM
Then show that part, because the sending part is a dead horse, but you are doing something strange by trying to receive it in a background thread.
Be aware that a beackground thread is not even a process in the way of a program. A Background thread is only a task which normally start and ends done inside the program.
I guess you are keeping it a live, but you let everybody guessing.
Success
Cor
Wednesday, November 16, 2016 10:29 PM
That code is for sending a message to a window. It is not good enough for communicating with a background process that does not have a window. You need to search for some better example.
You are actually right,,
But after thinking about the example, if it is a window like Notepad and i want to send text to it then i need to get the handle of the "Edit" child window, but how can i do it on other process without a specific child window? just like SendKey Method ?
The actual problem is that you are trying to use an undocumented interface. Sending keystrokes to the focus window is a blind flight, and if you want to send a message, you must specify the target. If you send a letter to someone, it's not different. It depends on the target process how you are finding out the target window (and it's handle). With spy++ (included in VS) you can examine the window structure. For example, with Notepad, the window class name of the editting control is "Edit", hence it works. But even if you find it out for the application in question, it could change after it's next update.
Armin
Thursday, November 17, 2016 12:22 AM
I believe SendKeys sends a keystroke to an active window. For example if Notepad is the active process and its edit window is the active window of the active process then SendKeys would send the keystrokes to the edit window and not somewhere else in Notepad.
Well, what i want is just sending the key to the process not to something specified in the process.
Plus it is a background process, so that is a little bit complicated to send a key to non-active process
Perhaps we could help if you told us what the name of the program is that you want to send the keys to. Also include the following information...
1. What control is it that you want to send the keys to? Or is it the actual window?
2. What key or keys do you want to send to this window or control?
Not all windows and controls can be sent keys or have their text set in the same way when you are trying to do it in a window that does not have focus. If you explain more about the program and what you want to accomplish by sending keys to it, there may be a better/different approach to take.
If you say it can`t be done then i`ll try it
Thursday, November 17, 2016 12:53 AM
That code is for sending a message to a window. It is not good enough for communicating with a background process that does not have a window. You need to search for some better example.
You are actually right,,
But after thinking about the example, if it is a window like Notepad and i want to send text to it then i need to get the handle of the "Edit" child window, but how can i do it on other process without a specific child window? just like SendKey Method ?
You have to be reasonably precise when sending a message to another process when its window is not active. That means you have to know which window you are sending the message to, unless it's a broadcast message, and you have to know what the message type and corresponding information is to be. It can't be arbitrary and there is no consistent pattern because application processes are generally different with respect to their use of windows and messages.
SendKeys assumes the keys are being send to the active application window, and that's half the battle. After that, you still need to know which keys the application window will process.
Paul ~~~~ Microsoft MVP (Visual Basic)
Friday, November 18, 2016 9:23 AM
Then show that part, because the sending part is a dead horse, but you are doing something strange by trying to receive it in a background thread.
Be aware that a beackground thread is not even a process in the way of a program. A Background thread is only a task which normally start and ends done inside the program.
I guess you are keeping it a live, but you let everybody guessing.
The process is in a background state ( not active ) but could be activate, all i need is sending keys while the process is non-activate.
Friday, November 18, 2016 9:43 AM
The actual problem is that you are trying to use an undocumented interface. Sending keystrokes to the focus window is a blind flight, and if you want to send a message, you must specify the target. If you send a letter to someone, it's not different. It depends on the target process how you are finding out the target window (and it's handle). With spy++ (included in VS) you can examine the window structure. For example, with Notepad, the window class name of the editting control is "Edit", hence it works. But even if you find it out for the application in question, it could change after it's next update.
I tried spy++ and got some good information, so the window we are talking about has no specific detectable classes inside, just an actual window, the handle was 0006039A, So how you suggest if i used the handle to send the keystrokes to the window ?
Friday, November 18, 2016 9:48 AM
Perhaps we could help if you told us what the name of the program is that you want to send the keys to. Also include the following information...
1. What control is it that you want to send the keys to? Or is it the actual window?
2. What key or keys do you want to send to this window or control?
Not all windows and controls can be sent keys or have their text set in the same way when you are trying to do it in a window that does not have focus. If you explain more about the program and what you want to accomplish by sending keys to it, there may be a better/different approach to take.
The process is an actual window, can be activated but i want to send it while it's not activated,
Also the keys i want to Send is not So Weird, let's say ( from F1, F9 | from a, z ), just a normal keys to use usually.
I had some other information about the window, and i hope you read the rest of the reply i sent here.
Friday, November 18, 2016 11:20 AM | 1 vote
Open Notepad and try this...
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("user32.dll", EntryPoint:="PostMessageW")>
Private Shared Function PostMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", EntryPoint:="FindWindowExW")>
Private Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr
End Function
Private Const WM_KEYDOWN As Integer = &H100
Private Const WM_CHAR As Integer = &H102
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim p As Process = Process.GetProcessesByName("notepad").FirstOrDefault
If p IsNot Nothing Then
Dim hWnd As IntPtr = FindWindowExW(p.MainWindowHandle, IntPtr.Zero, "edit", Nothing)
'sends uper and lower case letters and symbals to edit window
PostMessageW(hWnd, WM_CHAR, Asc("K"), 0)
PostMessageW(hWnd, WM_CHAR, Asc("e"), 0)
PostMessageW(hWnd, WM_CHAR, Asc("y"), 0)
PostMessageW(hWnd, WM_CHAR, Asc("s"), 0)
PostMessageW(hWnd, WM_CHAR, Asc("!"), 0)
'send F1 key to main window to open help
PostMessageW(p.MainWindowHandle, WM_KEYDOWN, Keys.F1, 0)
End If
End Sub
End Class
If you say it can`t be done then i`ll try it
Friday, November 18, 2016 11:25 AM
Go to a window in your house. Open it and then look if there is air coming in.
Then close your window and see if the window if the same quantity of air is still coming in.
There is endless times asked what you mean with closing the window and still want to receive data.
However, you only go on with sending this kind of bullying messages.
Success
Cor
Friday, November 18, 2016 11:31 AM | 1 vote
I tried spy++ and got some good information, so the window we are talking about has no specific detectable classes inside, just an actual window, the handle was 0006039A, So how you suggest if i used the handle to send the keystrokes to the window ?
The handle is just that piece of information that changes every time. But you can find it out like already shown (p.MainWindowHandle). You got examples.
Armin
Friday, November 18, 2016 12:23 PM
Open Notepad and try this...
Imports System.Runtime.InteropServices Public Class Form1 <DllImport("user32.dll", EntryPoint:="PostMessageW")> Private Shared Function PostMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport("user32.dll", EntryPoint:="FindWindowExW")> Private Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr End Function Private Const WM_KEYDOWN As Integer = &H100 Private Const WM_CHAR As Integer = &H102 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim p As Process = Process.GetProcessesByName("notepad").FirstOrDefault If p IsNot Nothing Then Dim hWnd As IntPtr = FindWindowExW(p.MainWindowHandle, IntPtr.Zero, "edit", Nothing) 'sends uper and lower case letters and symbals to edit window PostMessageW(hWnd, WM_CHAR, Asc("K"), 0) PostMessageW(hWnd, WM_CHAR, Asc("e"), 0) PostMessageW(hWnd, WM_CHAR, Asc("y"), 0) PostMessageW(hWnd, WM_CHAR, Asc("s"), 0) PostMessageW(hWnd, WM_CHAR, Asc("!"), 0) 'send F1 key to main window to open help PostMessageW(p.MainWindowHandle, WM_KEYDOWN, Keys.F1, 0) End If End Sub End Class
Ok this is a good example,
i tried to use it on other applications like Windows media player, it has a object named by (edit) also as notepad
The wmplayer didn't gave the same result as notepad, do you think there is a reason ?
Friday, November 18, 2016 12:25 PM
The handle is just that piece of information that changes every time. But you can find it out like already shown (p.MainWindowHandle). You got examples.
I understand that, Thanks for the help :)
Friday, November 18, 2016 12:47 PM
You must not use PostMessage() to send keys.
See R. Chen article
Friday, November 18, 2016 12:55 PM | 1 vote
Open Notepad and try this...
Imports System.Runtime.InteropServices Public Class Form1 <DllImport("user32.dll", EntryPoint:="PostMessageW")> Private Shared Function PostMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport("user32.dll", EntryPoint:="FindWindowExW")> Private Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr End Function Private Const WM_KEYDOWN As Integer = &H100 Private Const WM_CHAR As Integer = &H102 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim p As Process = Process.GetProcessesByName("notepad").FirstOrDefault If p IsNot Nothing Then Dim hWnd As IntPtr = FindWindowExW(p.MainWindowHandle, IntPtr.Zero, "edit", Nothing) 'sends uper and lower case letters and symbals to edit window PostMessageW(hWnd, WM_CHAR, Asc("K"), 0) PostMessageW(hWnd, WM_CHAR, Asc("e"), 0) PostMessageW(hWnd, WM_CHAR, Asc("y"), 0) PostMessageW(hWnd, WM_CHAR, Asc("s"), 0) PostMessageW(hWnd, WM_CHAR, Asc("!"), 0) 'send F1 key to main window to open help PostMessageW(p.MainWindowHandle, WM_KEYDOWN, Keys.F1, 0) End If End Sub End Class
Ok this is a good example,
i tried to use it on other applications like Windows media player, it has a object named by (edit) also as notepad
The wmplayer didn't gave the same result as notepad, do you think there is a reason ?
Yes, because it's a child window. It's not the main window. You would have to enumerate the child windows of the main window or parent until you find what you are looking for. See the example in the link below:
http://stackoverflow.com/questions/19719893/need-help-getting-child-windows
Paul ~~~~ Microsoft MVP (Visual Basic)
Friday, November 18, 2016 3:33 PM | 1 vote
Open Notepad and try this...
Imports System.Runtime.InteropServices Public Class Form1 <DllImport("user32.dll", EntryPoint:="PostMessageW")> Private Shared Function PostMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport("user32.dll", EntryPoint:="FindWindowExW")> Private Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr End Function Private Const WM_KEYDOWN As Integer = &H100 Private Const WM_CHAR As Integer = &H102 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim p As Process = Process.GetProcessesByName("notepad").FirstOrDefault If p IsNot Nothing Then Dim hWnd As IntPtr = FindWindowExW(p.MainWindowHandle, IntPtr.Zero, "edit", Nothing) 'sends uper and lower case letters and symbals to edit window PostMessageW(hWnd, WM_CHAR, Asc("K"), 0) PostMessageW(hWnd, WM_CHAR, Asc("e"), 0) PostMessageW(hWnd, WM_CHAR, Asc("y"), 0) PostMessageW(hWnd, WM_CHAR, Asc("s"), 0) PostMessageW(hWnd, WM_CHAR, Asc("!"), 0) 'send F1 key to main window to open help PostMessageW(p.MainWindowHandle, WM_KEYDOWN, Keys.F1, 0) End If End Sub End Class
Ok this is a good example,
i tried to use it on other applications like Windows media player, it has a object named by (edit) also as notepad
The wmplayer didn't gave the same result as notepad, do you think there is a reason ?
I think you should try the code at this link which gets windows of an external app. Run the keystroke sending app with admin privileges. You can see in image it sends keystrokes to edit window of "wmplayer". However that window typically requires focus to remove the word "Search" from the window when the user types which this app does not do and therefore you would have to perform that for an app such as wmplayer that requires similar necessities.
vb.net :: How can I make my program enter keys / do key input
La vida loca
Friday, November 18, 2016 4:27 PM
You must not use PostMessage() to send keys.
See R. Chen article
Yes, i agree, the Repeat Count, Scan Code, Extended Key Code, Context Code, Previous Key State, and the Transition State should all be combined and sent in the lParam of the PostMessage or SendMessage to make it a proper message. However, the SendInput function would require the other window to have focus set to it before the keys where sent which is what Zuher Laith wants to avoid doing i believe.
If the case was that the other window was going to have focus set to it first, then using the .net SendKeys class would be much easier than either of the SendInput or keybd_event win32 api functions. 8)
If you say it can`t be done then i`ll try it