Windows Analysis script

 

What does the Windows Analysis script do?

The Windows Analysis script (analysis.wbt) creates a report on the windows visible at the time the report is run.

The basic technique is to open the application and get the dialog boxes you are interested in displayed on the screen.

This Window Analysis script will display output detailing the contents of the window in question.

 

How do I use it?

Run the script, by double clicking on analysis.wbt (which is most likely located in the WinBatch\Samples subdirectory). A dialog with all the visible window titles, will appear. Choose the window of interest. The Window Analysis script will process and display the results.

Each window and control has its own unique window handle (often seen as hWnd or Wnd). Use the output of the Window Analysis script and the various cWndBy... functions in this extender to obtain the handle to the window or control you need, then use the specific functions designed for each type of control to either obtain information about the item, or to set it to the desired value.

The relationships, names, IDs, and exactly what windows controls are on the screen can get confusing. To help sort it out, run your application, and get to the point where the windows of interest are visible on the screen. Then run this script. It will create a report detailing the relationships between the windows and controls in your application. You can usually pick off window IDs, Names, and sequence numbers from the list to use in the Control Manager extender functions.

The IDs are usually the best to use if possible since they are unique, then the titles, then the sequence numbers. The sequence numbers are the most likely to change unexpectedly...

 

 

Windows Analysis Tutorial

Alphabetical: Function List

Control Type: Function List

 

 

;***************************************************************************
;**   Window Analysis Script
;**
;** This script creates a report on the windows visible at the time
;** the report is run.  Run the script.  Choose a top-level
;** window of interest, and it will show pertinent information
;** that may be necessary to use the Control Manager extender.
;**
;** Note that Tabbed dialogs sometimes must be displayed before
;** their controls are brought into existence.  So when using
;** tabbed dialogs, tab to the correct dialog first.  The
;** cWndInfo example shows how to move through a tabbed dialog.
;**
;** Revisions:
;**  6.0 July 7th 2011
;**      Load 64 bit Control manager when running 64 bit version of WinBatch.
;**
;**  5.0 Jan 7th 2010
;**      FIX: Handle titles with embedded double quotes. Fixes issue with
;**      ItemExtractCSV returning error 1707.
;**
;**  4.0 Sept 4th 2009
;**      FIX: Handle strings with embedded linefeeds. Fixes issue with
;**      ArrayFileGetCSV returning error 1808.
;**
;**  3.0 Sept 29th 2008
;**      FIX: Handle Windows Names that contain a comma.
;**
;**  2.0
; **     Initial Release
;**
;***************************************************************************
thisver = '6.0'
thistitle = 'Window Analysis'
csvfile ='Analysis.csv'
htmfile ='Analysis.htm'
; Application Data directory to store CSV file output
appdatadir = ShortCutDir( 'AppData', 0 , @TRUE ) : 'WinBatch\Temp\'
;Check if dir exists. it not create it
If !DirExist( appdatadir ) Then DirMake( appdatadir )
;if this is already running then exit
If WinExist( thistitle )
   WinActivate( thistitle )
   Exit
EndIf
;Tell Winbatch to be greedy
Exclusive(@ON)
;Load the Control Manager Extender
If WinMetrics(-3) == 5 Then AddExtender( 'wwctl64i.dll' )
Else AddExtender( 'wwctl44i.dll' )
;Handle errors
;Intcontrol( 73, 1, 0, 0, 0 )                    ; Use Goto ErrorHndlr
;Change to current working directory
wbtdir = FilePath( IntControl( 1004, 0, 0, 0, 0 ) )
DirChange( wbtdir )
;Get list of all windows currently on the screen
wins = WinItemize( )
If AskYesNo( 'Ok to Ignore', 'Duplicate, hidden and iconized windows will be removed from the list' ) == @YES
   AskMsg = 'Duplicate, hidden and iconized windows are not shown.'
   AskList = ''
   aCnts = ItemCount(wins, @TAB)
   For aCnt = 1 To aCnts
      Win = ItemExtract(aCnt, wins, @TAB)
      If (WinState(Win)!=-1 && WinState(Win)!=1)
         If !ItemLocate(Win, AskList, @TAB) Then AskList = ItemInsert(Win, -1, AskList, @TAB)
      EndIf
   Next
Else
   AskMsg = 'Showing all windows.'
   Asklist = wins
EndIf
trgWnd = AskItemlist(AskMsg, AskList, @TAB, @SORTED, @SINGLE)
;Get chosen window handle
hWnd=DllHwnd(trgWnd)
; Some error checking from the help file to make sure we have a valid handle to the target window.
hwndChk = DllHwnd(trgWnd)
Spec    = cWndGetWndSpec(hwndChk)         ; Get the window specification.
hWnd    = cWndByWndSpec(%Spec%)           ; Get the handle by the window specification.
If hWnd!=hwndChk                          ; Make sure the result matches the original handle
   Pause('ERROR!', "Could not get valid handle for %trgWnd% window.%@crlf%Exiting program.")
   ClipPut(Spec)
   Goto CANCEL
EndIf
GoSub InitUDFs
;Get maximum number of child levels
maxlevel = udfMaxLevelCount( hWnd, 1, 0 )  ;include parent by setting level to one
;Get total number of child windows
wincnt = udfWinCount( hWnd, 0 )
;Initialize database
; Format:
; RowNumber, MaxLevels, ParentCount,  [Child1, Child2, Child3, Etc ] , Class , Id , Title , WndStyle, WndStyleEx, ClassStyle
staticcols = 9
data =  ArrDimension( wincnt, maxlevel + staticcols - 1  ) ; Subtract one because Parent is included in maxlevel
ArrInitialize(data, '')
;Get Window data
info = udfGetWndInfo( hWnd )
name =  ItemExtractCSV( 1, info, 1 )
name = StrReplace( name, @LF, ' ' ) ; 4.0 fix
id =  ItemExtractCSV( 2, info, 1 )
class = ItemExtractCSV( 3, info, 1 )
wndsytle = ItemExtractCSV( 11, info, 1 )
wndstyleex = ItemExtractCSV( 12, info, 1 )
classstyle = ItemExtractCSV( 13, info, 1 )
; RowNumber, MaxLevels , ParentCount,  [Child1, Child2, Child3, Etc ] , Class , Id , Title , WndStyle, WndStyleEx, ClassStyle
data[0, 0] = 0 ;RowNumber
data[0, 1] =  maxlevel ;MaxLevels
data[0, 2] =  0  ;Parent
;data[0, 3] =  level  ; ;*Ignore* Child Windows
data[0, maxlevel+2 ]  = class ;Class
data[0, maxlevel+3 ]  = id    ;ID
data[0, maxlevel+4 ]  = name  ;Title
data[0, maxlevel+5 ]  = wndsytle ;WndStyle
data[0, maxlevel+6 ]  = wndstyleex  ;WndStyleEx
data[0, maxlevel+7 ]  = classstyle  ;ClassStyle
;Initalize Level
level = 0
;Gather CSV data about the window into the data array
udfGetWinData( hWnd, level, maxlevel, data )
; Write out CSV  the Application Data\Temp (C:\Documents and Settings\Deana\Application Data\WinBatch\Temp)
appdatadir = ShortCutDir( 'AppData', 0 , @TRUE ) : 'WinBatch\Temp\'
;Check if dir exists. it not create it
If !DirExist( appdatadir ) Then DirMake( appdatadir )
ArrayFilePutCSV( appdatadir : csvfile, data )
;Run(appdatadir : csvfile, '')
;Run('Notepad.exe', appdatadir : csvfile )
;***************************************************************************
;**
;**  Read CSV create HTML Table
;**
;***************************************************************************
headcolor = '#C0C0C0'
colcolors = '#EEEEFF,#DDDDFF,#CCCCFF,#BBBBFF,#AAAAFF,#9999FF'
greytext =  '#808080'
greybkgrnd = '#DBEADC'
greenbkgrnd = '#BAFEA3'
; Write out CSV  the Application Data\Temp (C:\Documents and Settings\Deana\Application Data\WinBatch\Temp)
appdatadir = ShortCutDir( 'AppData', 0 , @TRUE ) : 'WinBatch\Temp\'
;Check if dir exists. it not create it
If !DirExist( appdatadir ) Then DirMake( appdatadir )
csvdata = ArrayFileGetCSV(appdatadir : csvfile, 0)
; Database Format:
; RowNumber, MaxLevels, Parent,  [Child1, Child2, Child3, Etc ] , Class , Id , Title , WndStyle, WndStyleEx, ClassStyle
;Read max level from data
maxlevel = csvdata[0,1]
;Read parent windowname
topwin = csvdata[0,maxlevel + 4]
handle  = FileOpen( appdatadir: htmfile, 'Write')
FileWrite(handle, '<HTML>')
FileWrite(handle, '<HEAD></HEAD>')
FileWrite(handle, '<TITLE>' : thistitle: '</TITLE>')
FileWrite(handle, ' <!-- <DEFANGED_STYLE type="text/css"><!--p {font-family: Courier, monospace;font-size: 9pt;}TD{font-family: Courier, monospace; font-size: 9pt;}TH{font-family: Courier, monospace; font-size: 9pt;}--> --> </DEFANGED_STYLE>')
FileWrite(handle, '<BODY>')
FileWrite(handle, '<H2>': thistitle : ' ' :  thisver : '</H2><P>' : 'Windowname : ': topwin: '<BR>')
FileWrite(handle, 'Max Level : ' :  maxlevel : '<P>' )
FileWrite(handle, '<TABLE border="1" cellpadding="5">' )
; Write header for table
FileWrite(handle, '<TR bgcolor="':headcolor:'">' )
FileWrite(handle, '<TH>Parent<BR>&nbsp</TH>' )
For count = 1 To maxlevel-1
  FileWrite(handle, '<TH>Child<BR>': count :'</TH>' )
  If count == maxlevel - 1
      FileWrite(handle, '<TH>&nbsp</TH>' ) ; Write a blank col at the end of all the child windows
  EndIf
Next
FileWrite(handle, '<TH>Class</TH>' )
FileWrite(handle, '<TH>Id</TH>' )
FileWrite(handle, '<TH>Name</TH>' )
FileWrite(handle, '<TH>WndStyle</TH>' )
FileWrite(handle, '<TH>WndStyleEx</TH>' )
FileWrite(handle, '<TH>ClassStyle</TH>' )
FileWrite(handle, '</TR>' )
greenflag = 0
For darow = 0 To ArrInfo(csvdata, 1 )-1
   FileWrite(handle, '<TR>' )
   For dacol = 2 To ArrInfo(csvdata, 2 )-1
      data = csvdata[darow, dacol]
      ;Compare to previous data if one of the parent/child columns
      If dacol <= maxlevel+1
         ;Special Handling for first row
         If darow == 0 Then prevrow = ''
         Else prevrow = csvdata[darow-1, dacol]
         ;Need to decide Whether to Write in grey or green.
         If data == prevrow && greenflag == 0  ; if previous row matches current rowdata and green flag set to false
            ;if data == csvdata[darow-1, dacol];if previous row matches current rowdata
            FileWrite(handle, '<TD bgcolor="':greybkgrnd:'"><FONT COLOR="':greytext:'">' ); Grey
         Else
            FileWrite(handle, '<TD bgcolor="':greenbkgrnd:'">' ); Green
            greenflag = 1
         EndIf
         If data == ''
            FileWrite(handle, '&nbsp' )
         Else
            FileWrite(handle, data )
         EndIf
         FileWrite(handle, '</FONT></TD>' )
         If dacol == maxlevel+1 ; Write a blank col at the end of all the child windows
            FileWrite(handle, '<TD bgcolor="':greybkgrnd:'">&nbsp</TD>' ); Grey Empty Col
         EndIf
      Else
         ;Colorize all non - child window columns
         ;Get RGB
         rgb = ItemExtract( dacol-maxlevel-1, colcolors, ',' )
         FileWrite(handle, '<TD bgcolor=': rgb : '>' )
         If data == ''
            FileWrite(handle, '&nbsp' )
         Else
            FileWrite(handle, data )
         EndIf
         FileWrite(handle, '</TD>' )
      EndIf
   Next
   greenflag = 0
   FileWrite(handle, '</TR>' )
Next
FileWrite(handle, '</TABLE>' )
FileWrite(handle, '</BODY>')
FileWrite(handle, '</HTML>')
FileClose( handle )
Run( appdatadir: htmfile, '')
Exit
;***************************************************************************
;**
;**                User Defined Functions
;**
;***************************************************************************
:InitUDFs
#DefineFunction udfMaxLevelCount( WorkWnd, Level, MaxLevel )
   level = level + 1
   ;Locate child
   nextchild = cWndinfo( workwnd, 8 )
   While nextchild
      ;Keep track of the highest level number
      If level > MaxLevel
         MaxLevel = level
      EndIf
      ;Recurse
      MaxLevel = udfMaxLevelCount( nextchild, level, MaxLevel )
      ;Get next Sibling
      nextchild =  cWndinfo( nextchild, 6 )
   EndWhile
   Return MaxLevel
#EndFunction ;udfMaxLevelCount
#DefineFunction udfWinCount( WorkWnd, count )
   count = count + 1
   ;Locate child
   nextchild = cWndinfo( workwnd, 8 )
   While nextchild
      ;Recurse
      count = udfWinCount( nextchild, count )
      ;Get next Sibling
      nextchild =  cWndinfo( nextchild, 6 )
   EndWhile
   Return count
#EndFunction ;udfWinCount
#DefineFunction udfGetWinData( WorkWnd, level, maxlevel, data )
   delim = ','
   level = level + 1
   ;Keep track of row number
   ptr_rowcount = PtrPersistent( rowcount, 0 )
   *ptr_rowcount = *ptr_rowcount + 1
   ;Locate child
   nextchild = cWndinfo( workwnd, 8 )
   count = 0
   While nextchild
      count = count+1 ;Keeps track of Childcount windows
      ;Pause(count, *ptr_prevchild)
      ; Get Window Data
      info = udfGetWndInfo( nextchild )
      name =  ItemExtractCSV( 1, info, 1 )
      name = StrReplace( name, @LF, ' ' ) ; 4.0 fix
      id =  ItemExtractCSV( 2, info, 1 )
      class = ItemExtractCSV( 3, info, 1 )
      wndsytle = ItemExtractCSV( 11, info, 1 )
      wndstyleex = ItemExtractCSV( 12, info, 1 )
      classstyle = ItemExtractCSV( 13, info, 1 )
      ; RowNumber, MaxLevels , ParentCount,  [Child1, Child2, Child3, Etc ] , Class , Id , Title , WndStyle, WndStyleEx, ClassStyle
      row = *ptr_rowcount
      data[row, 0] = row+1      ;RowNumber -  add one because parent already written
      data[row, 1] = maxlevel ;MaxLevels
      data[row, 2] = 0             ;ParentCount will always be zero
      ; HandleChild Windows
      ; Keep track of previous childs
      For col = 3 To level+2 ;Loop once for each child
      ;Grab data from previous rows column
      prevdata = data[row-1, col]
      ;Check if col is equal to the current level plus 2
      If col == level+2
         data[row, level+2] = count ; insert child count number
      Else
         data[row, col] = prevdata ; insert data from previous line
      EndIf
      Next
      data[row, maxlevel+2 ]  = class ;Class
      data[row, maxlevel+3 ]  = id    ;ID
      data[row, maxlevel+4 ]  = name  ;Title
      data[row, maxlevel+5 ]  = wndsytle ;WndStyle
      data[row, maxlevel+6 ]  = wndstyleex  ;WndStyleEx
      data[row, maxlevel+7 ]  = classstyle  ;ClassStyle
      ;Recurse
      data = udfGetWinData( nextchild, level, maxlevel, data )
      ;Get next Sibling
      nextchild =  cWndinfo( nextchild, 6 )
   EndWhile
   Return data
#EndFunction ;udfGetWinData
#DefineFunction udfGetWndInfo( WorkWnd )
   ;Returns a delimited list of Window information
   delim = ','
   Title           = cWndinfo(WorkWnd, 0)
   Title = StrReplace( Title, '"', '""' ); 5.0 fix : Replace any embedded doublequotes in the title with double doublequotes
   ID              = cWndinfo(WorkWnd, 1)
   Class           = cWndinfo(WorkWnd, 2)
   Parent          = cWndinfo(WorkWnd, 3)
   FirstSibling    = cWndinfo(WorkWnd, 4)
   PreviousSibling = cWndinfo(WorkWnd, 5)
   NextSibling     = cWndinfo(WorkWnd, 6)
   LastSibling     = cWndinfo(WorkWnd, 7)
   FirstChild      = cWndinfo(WorkWnd, 8)
   Owner           = cWndinfo(WorkWnd, 9)
   WndStyle        = cWndinfo(WorkWnd, 20)
   WndStyleEx      = cWndinfo(WorkWnd, 21)
   ClassStyle      = cWndinfo(WorkWnd, 22)
   info = '"':Title:'"':delim:ID:delim:Class:delim:Parent:delim:FirstSibling:delim:PreviousSibling:delim:NextSibling:delim:LastSibling:delim:FirstChild:delim:Owner:delim:WndStyle:delim:WndStyleEx:delim:ClassStyle
   Return info
#EndFunction ;udfGetWndInfo
Return
;***************************************************************************
;**
;**             Cancel and Error Handling
;**
;***************************************************************************
:CANCEL
Exit
:WBERRORHANDLER
wErrFile = thisVer
wError=LastError()
wErrStr = IntControl(34,wError,0,0,0)
wErrLine = wberrorhandlerline
wErrOffset = wberrorhandleroffset
wErrAssign  = wberrorhandlerassignment
wErrMessage = 'Please email this info:%@CRLF%%@tab%"%wErrRptFile%"%@CRLF%to support@winbatch.com with the Subject line "Analysis Error"'
wErrTxt = StrCat(`wErrFile = `, wErrFile, @CRLF, `wError = `, wError, @CRLF, `wErrStr= `, wErrStr, @CRLF, `wErrLine = `, wErrLine, @CRLF, `wErrOffset = `, wErrOffset,@CRLF, `wErrAssign = `, wErrAssign, @CRLF, @CRLF, wErrMessage)
Pause( 'Notice', wErrTxt)
ClipPut(wErrTxt)
Goto CANCEL