none
Reading Status Bar in External App RRS feed

  • Question

  • So, i've looked every where and found all sorts of suggested methods to achieve this aim.

            Const SB_GETTEXT As Integer = &H402
            Const SB_GETTEXTLENGTH As Integer = &H403
            Const SB_GETPARTS As Integer = &H406
    
            ''' <summary>
            ''' 
            ''' </summary>
            ''' <param name="Index"></param>
            ''' <returns></returns>
            Public Function GetSBText(Optional ByVal Index As Integer = 0) As String
                If GetHandle(3000, 100) Then 'uses a hard coded ControlID to get the handle. so Handle is correct.
                    Dim parts As Long = SendMessageA(Handle, SB_GETPARTS, 0, 0)
                    If (parts > 0) AndAlso (Index < parts) Then
                        Dim iLen As Long = SendMessageA(Handle, SB_GETTEXTLENGTH, Index, 0)
                        Dim sText As String
    
                        If (iLen > 0) Then
    
                            sText = New String(vbNullChar, iLen)
                            iLen = SendMessage(Handle, SB_GETTEXT, Index, sText)
    
                            If iLen <> 0 Then
                                If sText.Trim = "" Then Return ""
                                sText = Strings.Left(sText, InStr(sText, vbNullChar) - 1)
                                Return sText
                            End If
                        Else
                            iLen = SendMessage(Handle, WM_GETTEXTLENGTH, 0, CStr(Nothing))
                            sText = Space(iLen + 1)
                            If SendMessage(Handle, WM_GETTEXT, CInt(iLen + 1), sText) <> 0 Then
                                If sText.Trim = "" Then Return ""
                                sText = Strings.Left(sText, InStr(sText, vbNullChar) - 1)
                                Return sText
                            End If
                        End If
                    End If
                End If
                Return ""
            End Function
    

    Pardon the VB.  I typically use C#, but editing old code and i'm a bit rusty.

    That being said, none of this works at all.  if my SendMessage returns In32 for SB_GETPARTS or SB_GETTEXTLENGTH i get an Arithmetic Overflow exception.  but when my Sendmessage returns a long

    Parts = 4423816314880
    iLen = 4410931412992 (regardless of the index parameter)

    this is not conducive to getting the appropriate text from the Status Bar.

    Does this mean something, like the SB is user drawn and thus I can't get the text?

    Thanks

    Jaeden "Sifo Dyas" al'Raec Ruiner


    "Never Trust a computer. Your brain is smarter than any micro-chip."
    PS - Don't mark answers on other people's questions. There are such things as Vacations and Holidays which may reduce timely activity, and until the person asking the question can test your answer, it is not correct just because you think it is. Marking it correct for them often stops other people from even reading the question and possibly providing the real "correct" answer.

    Thursday, July 6, 2017 7:57 PM

All replies

  • You must use GetWindowThreadProcessId()-OpenProcess(),
    VirtualAllocEx(), then SB_GETTEXT then ReadProcessMemory() to read text in another process

    And SB_GETPARTS or SB_GETTEXTLENGTH work for me

    Tested on Windows 10, on a 32-bit process, with a valid hWndStatusBar :

    Dim nParts As Integer = SendMessage(hWndStatusBar, SB_GETPARTS, 0, 0)
    Dim nTextLength As Integer = SendMessage(hWndStatusBar, SB_GETTEXTLENGTH, 0, 0)

    Declarations :

    Const WM_USER As Integer = &H400
    Const SB_GETPARTS As Integer = (WM_USER + 6)
    Const SB_GETTEXTLENGTHW As Integer = (WM_USER + 12)
    Const SB_GETTEXTLENGTH As Integer = SB_GETTEXTLENGTHW
    Const SB_GETTEXTW As Integer = (WM_USER + 13)
    Const SB_GETTEXT As Integer = SB_GETTEXTW
    
    <DllImport("User32.dll", EntryPoint:="SendMessageW", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer
        End Function



    • Edited by Castorix31 Friday, July 7, 2017 3:53 AM
    Friday, July 7, 2017 3:45 AM
  • "If GetHandle(3000, 100) Then 'uses a hard coded ControlID to get the handle. so Handle is correct."

    Handles are generated and assigned by the system at runtime.  You cannot hard-code a window handle because it is subject to change whenever the window is created.  As noted by Castorix31, you'll need to get the appropriate window handle at runtime.

    This may be just the first issue you need to correct.  Depending on the layout of the particular statusbar you are trying to access you may also need to enumerate some child controls within the statusbar to get the specific information you are after.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Friday, July 7, 2017 1:24 PM
    Moderator
  • ControlID does not Equal Handle.

    Using the ControlID you can get the Handle at run time.  That's what "GetHandle()" does.  I was trying to avoid responses like this by expressing this concept and reducing message size.  Too verbose, not verbose enough - can never win.

    Regardless, as it is, we have found that the StatusBar for the process we are looking at is being Owner Drawn, so not sure any system will be able to get the data.  (frankly i'm glad it's so complicated anyway, so we can use this as reasons for getting management to allow us to avoid using automation to begin with).

    Thanks

    Jaeden "Sifo Dyas" al'Raec Ruiner


    "Never Trust a computer. Your brain is smarter than any micro-chip."
    PS - Don't mark answers on other people's questions. There are such things as Vacations and Holidays which may reduce timely activity, and until the person asking the question can test your answer, it is not correct just because you think it is. Marking it correct for them often stops other people from even reading the question and possibly providing the real "correct" answer.

    Wednesday, July 12, 2017 5:47 PM
  • ControlID does not Equal Handle.

    Using the ControlID you can get the Handle at run time.  That's what "GetHandle()" does.  I was trying to avoid responses like this by expressing this concept and reducing message size.  Too verbose, not verbose enough - can never win.

    Regardless, as it is, we have found that the StatusBar for the process we are looking at is being Owner Drawn, so not sure any system will be able to get the data.  (frankly i'm glad it's so complicated anyway, so we can use this as reasons for getting management to allow us to avoid using automation to begin with).

    Thanks

    Jaeden "Sifo Dyas" al'Raec Ruiner


    "Never Trust a computer. Your brain is smarter than any micro-chip."
    PS - Don't mark answers on other people's questions. There are such things as Vacations and Holidays which may reduce timely activity, and until the person asking the question can test your answer, it is not correct just because you think it is. Marking it correct for them often stops other people from even reading the question and possibly providing the real "correct" answer.

    Well La dee da.

    Wednesday, July 12, 2017 7:07 PM