Click here to Skip to main content
15,885,173 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
See more:
Evening All,

Hoping you can offer some advice here. I am trying to get the control name of a window from another application. I have managed to get the hWnd via a class pre-written by another user (Obtained from Codeproject).

So i am declaring the SendMessage as follows:
VB
Declare Function SendMessageS Lib "user32" Alias "SendMessageA" (ByVal hwnd As IntPtr, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long


I have put this into a dummy application so chucked into form_load event. I loop through the top level windows, grab the handle and then enumerate child windows ensuring he MainWindowTitle matches a specific string value.

Then from this i enumerate all the child windows and try to perform a 'SendMessage' to get the control name from it. However when it hits this point it then throws a PInvoke error message as follows:

A call to PInvoke function 'WindowsApplication1!WindowsApplication1.Form1::SendMessageS' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.


Here is my Form_Load code, appreciate it if you could point me in the right direction.

VB
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Dim EnumWind As New WindowEnumeration
    Dim clsName As String = "WindowsForms10.Window.8.app.0.378734a"

    'Get a List of Top Window Belonging to: "WindowsForms10.Window.8.app.0.378734a"
    For Each TopWin As ApiWindow In EnumWind.GetTopLevelWindows(clsName)
        'Check the title of the Screen
        If (TopWin.MainWindowTitle = "Card Payment Screen") Then
            'We have the payment Screen

            'Enumerate all Child Windows (Controls) Passing Parent hWnd
            For Each ChildWin As ApiWindow In EnumWind.GetChildWindows(TopWin.hWnd)
                Dim WM_GETCONTROLNAME As Long = 50721
                Dim sText As String = Space(100)
                Try
                    'We get a stack PInvoke Error Here
                    SendMessageS(ChildWin.hWnd, WM_GETCONTROLNAME, 100, sText)
                Catch ex As Exception

                End Try
            Next
        End If
    Next
End Sub



Many Thanks
Dev
Posted
Comments
Sergey Alexandrovich Kryukov 22-Apr-15 15:29pm    
Why, why P/Invoking this?
—SA

For your P/Invoke declaration, the wMsg parameter should be an Integer, not a Long. The parameter is a 32-bit integer, whereas Long is a 64-bit integer.

The wParam parameter and return values should be IntPtr, since their size depends on whether you're running as a 32-bit or 64-bit process.

When you expect the function to update a string parameter, you should pass a StringBuilder. In .NET, the String type is immutable.

However, from what I've read, when the window belongs to another process, you have to allocate a buffer for the name in that process. This means you'll need to call OpenProcess, VirtualAllocEx, SendMessage, ReadProcessMemory, and finally VirtualFreeEx.

There's a two-part MSDN blog post from 2006 with the C# code to do this:
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 22-Apr-15 15:35pm    
5ed. I also provided a reference to the site which gives us correct P/Invoke signatures of Windows API.
—SA
Dev O'Connor 22-Apr-15 16:14pm    
Hi, yes it is grabbing the control from another process. i will look further into this then, if you have any VB.net code samples i would be greatly appreciated
Sascha Lefèvre 22-Apr-15 17:16pm    
+5
Please see my comment to the question. .NET will never work with "SendMessageA" (unless you do special marshaling), because .NET works with Unicode, not ASCII. It would be better to use "SendMessageA". Unbalance stack is the sign if using wrong signature, wrong number and/or sizes of parameters.

This is how you P/Invoke it: http://pinvoke.net/default.aspx/user32.SendMessage[^].

The whole idea to "integrate" applications via Windows messages sounds way too dirty to me to take it serious. I would like to say: "don't integrate, do software development".

—SA
 
Share this answer
 
Comments
Dev O'Connor 22-Apr-15 16:04pm    
The application i am currently making interfaces two peices of software (bridge) so when a certain field / action is entered then another action needs to take place on the other software.

We have spoken to them and they have confirmed they will not make the code changes to interface the two peices of software so .... here we are lol!
Sergey Alexandrovich Kryukov 22-Apr-15 16:10pm    
Well, whatever. Now, does this answer works for your?
—SA
Dev O'Connor 22-Apr-15 16:19pm    
Yes, i have reviewed both yours and Richards answers and both of them will help me achieve what i am looking to achieve, appreciate your time.
Sergey Alexandrovich Kryukov 22-Apr-15 18:40pm    
Great.
Good luck, call again.
—SA
Sascha Lefèvre 22-Apr-15 17:18pm    
+5

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900