Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

PBWin: screen scrape a DOS application

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PBWin: screen scrape a DOS application

    Code:
    ' Screen scrape a DOS application in 99 lines (could be less!).
    ' Fills in a listbox with all top level apps.
    ' select one and press the button to attempt to attach a console and see the screen
    ' Chris Holbrook 4 Jul 2008. With thanks to Eros Olmi
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "WIN32API.INC"
    %IDD_DIALOG1  =  101
    %IDC_LISTBOX1 = 1001
    %IDC_BUTTON1  = 1002
    DECLARE FUNCTION AttachConsole LIB "kernel32.dll"  ALIAS "AttachConsole" (dwProcessId AS DWORD) AS LONG
    DECLARE FUNCTION GetConsoleWindow LIB "kernel32.dll"  ALIAS "GetConsoleWindow" AS LONG
    TYPE WinInfoType
        WinTitle AS STRING * 256
        WinHandle AS LONG
    END TYPE
    GLOBAL gWinList() AS WinInfoType
    GLOBAL gWinListPos AS LONG
    '------------------------------------------------------------------------------
    FUNCTION GetWindowsByTitle(hD AS DWORD, lCtl AS LONG) AS LONG
        LOCAL Count             AS LONG
        LOCAL hW                AS DWORD
        LOCAL  dwpid            AS DWORD PTR
    
        gWinListPos = 0
        EnumWindows CODEPTR(EnumWindowsProc), 0
        FOR Count = 1 TO gWinListPos
            hW = gWinList(Count).WinHandle
            IF IsWindowVisible( hW ) THEN LISTBOX ADD hd, lctl, LTRIM$(STR$(hW,8)) + " : " + gWinList(Count).WinTitle
        NEXT Count
    END FUNCTION
    '--------------------------------------------------------------------------------
    FUNCTION EnumWindowsProc(BYVAL lHandle AS LONG, BYVAL lNotUsed AS LONG) AS LONG
        DIM wTitle AS STRING
        DIM lPos AS LONG
    
        wTitle = STRING$(256,0)
        GetWindowText lHandle, BYVAL STRPTR(wTitle), 256
        wTitle = EXTRACT$(wTitle, CHR$(0))
        IF LEN(wTitle) THEN
            INCR gWinListPos
            REDIM PRESERVE gWinList(gWinListPos)
            gWinList(gWinListPos).WinTitle = wTitle
            gWinList(gWinListPos).WinHandle = lHandle
        END IF
        FUNCTION = 1
    END FUNCTION
    '-------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
        LOCAL s                 AS STRING
        STATIC dwpid            AS DWORD PTR
        STATIC hWnd, hConsole             AS DWORD
        STATIC szbuffer         AS ASCIZ * 65536
        LOCAL lcount             AS LONG
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                GetWindowsByTitle ( CBHNDL, %IDC_LISTBOX1)
    
            CASE %WM_COMMAND
                SELECT CASE AS LONG CBCTL
                    CASE %IDC_BUTTON1
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            LISTBOX GET TEXT CBHNDL, %IDC_LISTBOX1 TO s
                            hWNd = VAL(TRIM$(PARSE$(s," ",1)))
                            getWindowThreadProcessID(hWnd,BYVAL VARPTR(dwPid))
                            IF AttachConsole(@dwpid) = 0 THEN
                                ? "failed to attach console",%MB_TASKMODAL,"error"
                                EXIT SELECT
                            END IF
                            hConsole = GetStdHandle(%STD_OUTPUT_HANDLE)
                            GetConsoleWindow
                            IF 0 = readConsoleOutputCharacter(hConsole, BYVAL VARPTR (szbuffer), 2000, BYVAL 0, lcount) THEN
                                ? "failed to read console",%MB_TASKMODAL,"error"
                                EXIT SELECT
                            END IF
                            ? STR$(lcount) + szbuffer
                            FreeConsole ()
                        END IF
                END SELECT
        END SELECT
    END FUNCTION
    '----------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "Screen Scrape DOS APP", 141, 121, 197, 185, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU _
            OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_SYSMODAL OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, _
            %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
        CONTROL ADD LISTBOX, hDlg, %IDC_LISTBOX1, , 15, 10, 170, 85
        CONTROL ADD BUTTON,  hDlg, %IDC_BUTTON1, "Button1", 155, 105, 30, 15
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
        FUNCTION = lRslt
    END FUNCTION
    '================================================================
    FUNCTION PBMAIN()
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION

  • #2
    Chris, I read your posting here when you first put it up.
    I am finally able to use it bc we have windows xp on some machines and our console program lacks some needed features and I can get use of data off the screen to help workstations on some things they want .
    The code does not work on windows 2000 as the AttachConsole API is only supported starting with Windows XP.
    So I reworked your code a bit to help others make use of your work.
    Thanks Chris.
    Last edited by Paul Purvis; 24 Apr 2014, 03:00 AM.
    p purvis

    Comment


    • #3
      Program to send a windows handle number to standard output, mostly used in batch programming

      Code:
      'conswhnd.bas
      'returns the console window handle
      
      #COMPILE EXE
      FUNCTION PBMAIN () AS LONG
      STDOUT TRIM$(STR$(CONSWHND))
      END FUNCTION

      A batch file to set the output to an environmental variable named CONSOLEWINDOWHANDLE

      Code:
      @echo off
      SET CONSOLEWINDOWHANDLE=
      FOR /F "tokens=*" %%i in ('CONSWHND') do SET CONSOLEWINDOWHANDLE=%%i 
      
      REM CONTINUE YOUR BATCH CODE HERE
      PAUSE
      EXIT
      Attached Files
      Last edited by Paul Purvis; 24 Apr 2014, 02:53 AM.
      p purvis

      Comment


      • #4
        Program to display the console window from a batch file.
        Program makes use of the an evironmential variable named CONSOLEWINDOWHANDLE that should be set in a batch file or the handle should be passed as a parameter in the command line
        i actually did not test the command line effect but added it in

        Code:
        'compiled with pbwin9.05
        #COMPILE EXE
        #DIM ALL
        #INCLUDE "WIN32API.INC"
        DECLARE FUNCTION AttachConsole LIB "kernel32.dll"  ALIAS "AttachConsole" (dwProcessId AS DWORD) AS LONG
        DECLARE FUNCTION GetConsoleWindow LIB "kernel32.dll"  ALIAS "GetConsoleWindow" AS LONG
        
        FUNCTION PBMAIN
            DIM  dwpid            AS DWORD PTR
            STATIC hWnd, hConsole   AS DWORD
            DIM  szbuffer         AS ASCIZ * 65536
            DIM iConsolewindowhandle AS LONG
            DIM sConsolewindowhandle AS STRING
            LOCAL lcount             AS LONG
            LOCAL iwindowhandlefound AS LONG
        
            sConsolewindowhandle=ENVIRON$("CONSOLEWINDOWHANDLE")
            IF LEN(sConsolewindowhandle) THEN
              iConsolewindowhandle=VAL(sConsolewindowhandle)
              ELSE
              iConsolewindowhandle=VAL(TRIM$(COMMAND$))
            END IF
            SLEEP 1000
            IF iConsolewindowhandle<1& THEN
                ? "The console window handle should be put on the command line or"+$CRLF+"   set in the environment variable CONSOLEWINDOWHANDLE"
                EXIT FUNCTION
            END IF
            hWNd = iConsolewindowhandle
            getWindowThreadProcessID(hWnd,BYVAL VARPTR(dwPid))
        
            IF dwpid THEN iwindowhandlefound=1&
        
            WHILE iwindowhandlefound
               IF AttachConsole(@dwpid) = 0& THEN
                   iwindowhandlefound=0&
                   ITERATE
                  '? "failed to attach console",%MB_TASKMODAL,"error"
                  ' EXIT FUNCTION
                END IF
               hConsole = GetStdHandle(%STD_OUTPUT_HANDLE)
               GetConsoleWindow
               IF 0 = readConsoleOutputCharacter(hConsole, BYVAL VARPTR (szbuffer), 2000, BYVAL 0, lcount) THEN
                  ? "failed to read console",%MB_TASKMODAL,"error"
                  iwindowhandlefound=0&
                  FreeConsole ()
                  ITERATE
               END IF
               FreeConsole ()
               ? "Number of chararcter found in the console screen buffer -"+STR$(lcount)+$CRLF+RIGHT$(szbuffer,lcount)
               SLEEP 3000
               WEND
        
        END FUNCTION
        Attached Files
        p purvis

        Comment


        • #5
          the full batch file to make the console program and gui program work
          Code:
          @echo off
          SET CONSOLEWINDOWHANDLE=
          FOR /F "tokens=*" %%i in ('CONSWHND') do SET CONSOLEWINDOWHANDLE=%%i 
          START SCRAPCON.EXE
          
          
          REM CONTINUE YOUR BATCH CODE HERE
          PAUSE
          When the batch program is completed, then SCRAPCON.EXE will end.
          If you do not use the
          FreeConsole ()
          line. The console program will not end. See MSDN on the subject.
          Last edited by Paul Purvis; 24 Apr 2014, 11:31 PM.
          p purvis

          Comment


          • #6
            So I reworked your code a bit to help others make use of your work.
            You're welcome Paul. I could not have produced the original without help from Eros, you used my code, many people can benefit from the result. For me, this is what the forums are about.

            Comment


            • #7
              I wrote a DOS/console screen-scraper many years ago, and PB sold it for a while. As I remember it, scraping Windows Platform 1 (95/98/SE) was 100% different from Platform 2 (starting with NT) and NT was significantly different from... some later version, I forget. I only bring it up because if somebody is dealing with DOS programs they might also be working with Platform 1.
              "Not my circus, not my monkeys."

              Comment


              • #8
                Just reviewing the code that I posted.
                Freeconsole() should be put ahead of msgbox statement.

                Code:
                IF 0 = readConsoleOutputCharacter(hConsole, BYVAL VARPTR (szbuffer), 2000, BYVAL 0, lcount) THEN
                        FreeConsole ()
                        ? "failed to read console",%MB_TASKMODAL,"error"
                        iwindowhandlefound=0& 
                        ITERATE
                 END IF
                I am not going to write the code or change the zipped file.
                It is a small oversite for testing purposes.
                An actual useful program would probably not even want to send a message on an error. A actual program would be custom coded anyways.
                Last edited by Paul Purvis; 24 Apr 2014, 11:44 PM.
                p purvis

                Comment


                • #9
                  a simpler command line to use in a batch file without using tokens with the windows os FOR command line statement.

                  Code:
                  FOR /F %%A IN ('CONSWHND') DO SET CONSOLEWINDOWHANDLE=%%A
                  if not used in a batch file and only typed on the command line, replace double %% with % like the below
                  Code:
                  FOR /F %A IN ('CONSWHND') DO SET CONSOLEWINDOWHANDLE=%A
                  p purvis

                  Comment


                  • #10
                    Modified to work with PBWin10 on Windows 7

                    Code:
                    ' Screen scrape a DOS application in 99 lines (could be less!).
                    ' Fills in a listbox with all top level apps.
                    ' select one and press the button to attempt to attach a console and see the screen
                    ' Chris Holbrook 4 Jul 2008. With thanks to Eros Olmi
                    '
                    ' amended to work with PBWin 10 17 July 2018
                    '
                    #compile exe
                    #dim all
                    #include "WIN32API.INC"
                    %IDD_DIALOG1  =  101
                    %IDC_LISTBOX1 = 1001
                    %IDC_BUTTON1  = 1002
                    '
                    type WinInfoType
                        WinTitle as string * 256
                        WinHandle as long
                    end type
                    global gWinList() as WinInfoType
                    global gWinListPos as long
                    '------------------------------------------------------------------------------
                    function GetWindowsByTitle(hD as dword, lCtl as long) as long
                        local count             as long
                        local hW                as dword
                        local  dwpid            as dword ptr
                    
                        gWinListPos = 0
                        EnumWindows codeptr(EnumWindowsProc), 0
                        for count = 1 to gWinListPos
                            hW = gWinList(count).WinHandle
                            if IsWindowVisible( hW ) then listbox add hd, lctl, ltrim$(str$(hW,8)) + " : " + gWinList(count).WinTitle
                        next count
                    end function
                    '--------------------------------------------------------------------------------
                    function EnumWindowsProc(byval lHandle as long, byval lNotUsed as long) as long
                        dim wTitle as string
                        dim lPos as long
                    
                        wTitle = string$(256,0)
                        GetWindowText lHandle, byval strptr(wTitle), 256
                        wTitle = extract$(wTitle, chr$(0))
                        if len(wTitle) then
                            incr gWinListPos
                            redim preserve gWinList(gWinListPos)
                            gWinList(gWinListPos).WinTitle = wTitle
                            gWinList(gWinListPos).WinHandle = lHandle
                        end if
                        function = 1
                    end function
                    '-------------------------------------------------------------------
                    callback function ShowDIALOG1Proc()
                        local s                 as string
                        static dwpid            as dword ptr
                        static hWnd, hConsole             as dword
                        static szbuffer         as asciz * 65536
                        local lcount             as long
                    
                        select case as long cbmsg
                            case %wm_initdialog
                                GetWindowsByTitle ( cbhndl, %IDC_LISTBOX1)
                    
                            case %wm_command
                                select case as long cbctl
                                    case %IDC_BUTTON1
                                        if cbctlmsg = %bn_clicked or cbctlmsg = 1 then
                                            listbox get text cbhndl, %IDC_LISTBOX1 to s
                                            hWNd = val(trim$(parse$(s," ",1)))
                                            getWindowThreadProcessID(hWnd,dwPid)
                                            if AttachConsole(dwpid) = 0 then
                                                ? "failed to attach console",%mb_taskmodal,"error"
                                                exit select
                                            end if
                                            hConsole = GetStdHandle(%STD_OUTPUT_HANDLE)
                                            GetConsoleWindow
                                            if 0 = readConsoleOutputCharacter(hConsole, byval varptr (szbuffer), 2000, byval 0, lcount) then
                                                ? "failed to read console",%mb_taskmodal,"error"
                                                exit select
                                            end if
                                            ? str$(lcount) + szbuffer
                                            FreeConsole ()
                                        end if
                                end select
                        end select
                    end function
                    '----------------------------------------------------------------
                    function ShowDIALOG1(byval hParent as dword) as long
                        local lRslt as long
                        local hDlg  as dword
                    
                        dialog new hParent, "Screen Scrape DOS APP", 141, 121, 197, 185, %ws_popup or %ws_border or %ws_dlgframe or %ws_sysmenu _
                            or %ws_clipsiblings or %ws_visible or %ds_sysmodal or %ds_modalframe or %ds_3dlook or %ds_nofailcreate or %ds_setfont, _
                            %ws_ex_controlparent or %ws_ex_left or %ws_ex_ltrreading or %ws_ex_rightscrollbar, to hDlg
                        control add listbox, hDlg, %IDC_LISTBOX1, , 15, 10, 170, 85
                        control add button,  hDlg, %IDC_BUTTON1, "ATTACH", 155, 105, 40, 15
                        dialog show modal hDlg, call ShowDIALOG1Proc to lRslt
                        function = lRslt
                    end function
                    '================================================================
                    function pbmain()
                        ShowDIALOG1 %hwnd_desktop
                    end function

                    Comment

                    Working...
                    X
                    😀
                    🥰
                    🤢
                    😎
                    😡
                    👍
                    👎