Question SendMessage win32 API

Hillis1988

New member
Joined
Mar 20, 2015
Messages
4
Programming Experience
3-5
Hi ladies and gents,
I have been making something which harvests data from a sybase system which is linked through MS Access. It is a terrible system in the making, but unfortunately i do not have any better way to do it in the environment I have, as the access DB is needed by a whole bunch of other dependencies made by others.

I have a console app built using vb2010 and .NET 4.0 that needs to put a password into a sybase popup box which asks for credentials, I need to do this because this same box prevents all of my automation running whilst it waits on a password. Although I havn't built it yet here is my intention.

  • Open the thing that requires the logon to sybase,
  • Wait until I find a window handle for a window with caption "Logon to Sybase"
  • Dump the password in the box
  • Press the ok button
  • wait a second, then proceed.

Here is the code I have, which is simply trying to send the text to the text box. I know I have the correct Window Handles as I have used WinSpy , and I know they are editable boxes programmatically, because WinSpy can edit them from within itself.
I figured there is no point writing the rest of the code until I get this bit working, so if anyone who can tell me what is wrong with this it would be greatly appreciated.

PS: The code is not smoothed out as I am experimenting, so please forgive :)



Module Module1
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWndParent As IntPtr, ByVal hWndChildAfter As Integer, ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal wMsg As Long, ByVal wParam As IntPtr, ByVal lParam As String) As Long
Private Enum WindowMessages
WM_SETTEXT = &HC
End Enum


Sub Main()
Dim hWnd As IntPtr = FindWindow(vbNullString, "Logon to Sybase")
Console.WriteLine(hWnd) 'confirmed correct with WinSpy++
Dim hWndStatic As IntPtr = FindWindowEx(hWnd, IntPtr.Zero, "edit", "")
Console.WriteLine(hWndStatic) 'confirmed correct with WinSpy++
Dim hWndStatic2 As IntPtr = FindWindowEx(hWnd, hWndStatic, "Edit", "")
Console.WriteLine(hWndStatic2) 'confirmed correct with WinSpy++
Dim hWndStatic3 As IntPtr = FindWindowEx(hWnd, hWndStatic2, "Edit", "")
Console.WriteLine(hWndStatic3) 'confirmed correct with WinSpy++
Dim editTxt As String
editTxt = "Password"
Threading.Thread.Sleep(1000) 'it sometimes hasnt drawn the window so it returns nothing


SendMessage(hWndStatic3, WindowMessages.WM_SETTEXT, 0, editTxt)


Console.ReadLine()
End Sub


End Module
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,545
Location
Norway
Programming Experience
10+
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal wMsg As Long, ByVal wParam As IntPtr, ByVal lParam As String) As Long
Change wMsg parameter type to 32bit integer, and return type to IntPtr.
According to SendMessage function (Windows) and Windows Data Types (Windows).

I think "lParam As String" should work.
 

Hillis1988

New member
Joined
Mar 20, 2015
Messages
4
Programming Experience
3-5
Thanks for the response, just tried as suggested and still no luck unfortunately. lParam is usually a int32 or intPtr according to the MSDN source you listed. The interesting thing with this is that if I change the handle to an empty notepad window, it works.

below is me showing that all my handles match up with a screenshot of the box I am trying to populate. Absolutely no idea what is going on. Once again, any help anyone can be at even giving me something else to try, would be deeply appreciated,

Even more irritating, I know it must be possible, because WinSpy allows me to change the password box without any issues, so if WinSpy can do it, there must be a way to use a windows API to populate that box.

.netForumExport.PNG
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,545
Location
Norway
Programming Experience
10+
The additional explanation is that l/h parameters are pointers/handles and usually type IntPtr that varies in size according to 32/64bit OS.
The wMsg parameter is 32bit regardless (and same as underlying type of WindowMessages enumeration), and doesn't matter is signed/unsigned when value can be either.
lParam is "message specific" and can usually be changed to the relevant type of data to send, type String is common here.
If the original code worked without throwing exception it must mean you run in 64bit mode.

Not sure why it "doesn't work".
 

Hillis1988

New member
Joined
Mar 20, 2015
Messages
4
Programming Experience
3-5
Ah i see, the original API call reference that I used said type [Any] on lParam, which I assumed meant that I could change it to a string at the time. The MSDN reference then contradicted that when I read it, hence why I got confused,

To be honest, the code does actually work, it works if I use it to populate notepad, so I dont think it is actually an issue with the code, probably more my application of the code itself. I am beginning to wonder if it is something to do with 64bit windows?? In all honesty, I don't know enough about it to even begin to troubleshoot it, as this is the first time I have gone near User32, as I am primarily a WebDev man, so never needed it.

Do you think it is possible that it is a OS issue as opposed to a programming one? If so, any ideas on how I could test it?

Thanks again for the response and explanation John,
Roy
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,545
Location
Norway
Programming Experience
10+
my previous post said:
If the original code worked without throwing exception it must mean you run in 64bit mode.
When I think about it your original "wMsg As Long" should have thrown a PInvokeStackImbalance exception, since that will not be valid for neither 32/64bit.
the code does actually work, it works if I use it to populate notepad
I read that as with my modifications applied, that you confirmed earlier.
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,545
Location
Norway
Programming Experience
10+
If you haven't already, I suggest you try running your app as elevated admin (right click .exe and select "run as administrator"). You can also run VS as elevated admin, and debugging will then also run in same context.
 

Hillis1988

New member
Joined
Mar 20, 2015
Messages
4
Programming Experience
3-5
Ok, so I managed to get it to work in VBA, it ran second time with the exact same code except converted Intptr's to longs. I still have a feeling that int64 is confusing it though, as an IntPtr will give me a int64 on a 64 bit OS because its a platform specific struct, and so will a long. VBA's long is a Int32 so it kind of makes a little bit of sense that it wont even throw me an exception.

Will let you know when I get a chance to test in production environment :)

Thanks again.



When I think about it your original "wMsg As Long" should have thrown a PInvokeStackImbalance exception, since that will not be valid for neither 32/64bit.

PS: You're right, VBA bombed straight away on this, so thanks for pointing that out! Its just bizarre that VBA threw an error and .NET didn't, which makes me thing something else is at work.
 
Top Bottom