Sneaky Export Data from Applications

The other day I wanted to pull some data out of a standalone application.
The application is like a database. Records are presented one at a time on a single screen.
Navigation buttons allowed First, Previous, Next, Last.

So, you can input OK, print OK, but when it comes to a data dump – no way – no how. No Export menu.

The data file didn’t look nice – binary. The strings were only partly visible – I didn’t fancy that track.

I might have tried setting up a Text File Printer (a fake printer which prints to a text file), but I thought I’d try something new.

Using Spy++, I discovered all of the data on screen were contained in separate textboxes.
(no Spy++ ??, Try Winspector)

Not all of the textboxes were useful, but I could massage the data later.

So here’s what the code does:
1. Get the Application Window Handle – hWnd
2. Walk the hierarchy and GetText each window.
3. Once walking done, Click the Next button
Repeat at 2

Declare Function GetDesktopWindow Lib “user32” () As Long
Declare Function GetWindow Lib “user32” (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Declare Function FindWindowEx Lib “user32” Alias “FindWindowExA” (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Declare Function SendMessage Lib “user32” Alias “SendMessageA” (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Function PostMessage Lib “user32” Alias “PostMessageA” (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function GetWindowLong Lib “user32” Alias “GetWindowLongA” (ByVal hWnd As Long, ByVal nIndex As Long) As Long
 
Dim rng As Range
 
Sub Extract()
    Dim hWnd As Long, i As Long
 
    Set rng = Selection
 
    hWnd = GetDesktopWindow()
    hWnd = FindWindowLike(hWnd, “My Application *”)
 
    For i = 1 To 100
        WalkWindowsText hWnd
        Set rng = Cells(rng.Row + 1, 1)
        ClickButton hWnd, “Next”
    Next
 
    rng.Select
End Sub
 
Sub WalkWindowsText(hWndParent As Long)
    Dim hWnd As Long, lng As Long, str As String
 
    Do
        hWnd = FindWindowEx(hWndParent, hWnd, vbNullString, vbNullString)
        If hWnd <> 0 Then
            rng.Value = WindowText(hWnd)
            Set rng = rng.Offset(, 1)
            WalkWindowsText hWnd
        End If
    Loop Until hWnd = 0
End Sub
 
Function ClickButton(hWndParent As Long, ButtonText As String)
    Const WM_COMMAND = &H111, GWL_ID = (-12)
 
    Dim hWnd As Long, lngID As Long
 
    hWnd = FindWindowEx(hWndParent, 0, “Button”, ButtonText)
    lngID = GetWindowLong(hWnd, GWL_ID)
    PostMessage hWndParent, WM_COMMAND, lngID And &HFFFF&, hWnd
End Function
 
Function FindWindowLike(hWndParent As Long, Caption As String) As Long
    Const GW_HWNDNEXT = 2, GW_CHILD = 5
 
    Dim hWnd As Long, str As String, lng As Long
 
    hWnd = GetWindow(hWndParent, GW_CHILD)
    Do Until hWnd = 0
        If WindowText(hWnd) Like Caption Then
            FindWindowLike = hWnd
            Exit Do
        End If
 
        hWnd = GetWindow(hWnd, GW_HWNDNEXT)
    Loop
End Function
 
Function WindowText(hWnd As Long) As String
    Const WM_GETTEXT = &HD, WM_GETTEXTLENGTH = &HE
 
    Dim lng As Long, str As String
 
    If hWnd <> 0 Then
        lng = SendMessage(hWnd, WM_GETTEXTLENGTH, 0&, 0&) + 1
        If lng > 0 Then
            str = String$(lng, vbNullChar)
            lng = SendMessage(hWnd, WM_GETTEXT, lng, ByVal str)
            If lng > 0 Then WindowText = Left$(str, lng)
        End If
    End If
End Function
Posted in Uncategorized

4 thoughts on “Sneaky Export Data from Applications

  1. I’ll have to pull this down a take a poper look, but the “Walk the hierarchy and GetText each window” bit sounds useful.

    Too a look at that spy++ replacement, is it any good? – i’ve never had any issu ewith spymyself, but i might give it a whrill.

    cheers Rob

Leave a Reply

Your email address will not be published. Required fields are marked *