Microsoft KB Archive/136208

= Microsoft Knowledge Base =

Techniques for Determining When a Task Has Completed
Last reviewed: July 25, 1996

Article ID: Q136208

The information in this article applies to:


 * Microsoft Visual Test for Windows 95 and Windows NT, version 4.0

SUMMARY
This article outlines techniques you can use to determine when a task has completed.

Timing is critical to developing sound Test scripts. Often a Test script must wait for an application task to complete before it can continue processing. Typically, applications perform many tasks, all of which require various indeterminate amounts of time to complete, such as file copy routines in an installation program or database queries. Factors that influence task completion times in the computing environment include processor speed, multitasking, and scheduling. Therefore, you need reliable techniques for determining when a task has completed.

MORE INFORMATION
The techniques discussed include:


 * Detecting changes to controls in the user interface (UI).
 * Detecting Window creation and destruction by using notifications and by using the WFndWndC function.
 * Detecting graphical changes to the user interface.
 * Using WaitUntilIdle to determine when the system has gone idle.

NOTE: Some of the examples use the WordPad program used in Windows 95, which is different from the Write program used in Windows NT version 3.51 and earlier. However, the examples apply to both applications.

Detecting Changes to Controls in the UI
In this example, the script detects changes to the text in an edit control to determine when the task has completed. You can apply the same logic to detect changes to text in a window caption or static control, to detect other changes to controls, or to detect controls added to the interface.

  Insert the following code into a new window: '$include 'declares'

Dim TextWindow as HWND Dim CurrentWindow as HWND Dim Timer1 as Double Dim hwndButton as HWND Dim counter as integer counter = 0

'note you may be required to change the path name to Wordpad Run "c:\program files\accessories\Wordpad.exe", NoWait Sleep 2

'obtain a handle to the edit box in WordPad TextWindow = WFndWndWaitC("", "RICHEDIT", FW_FOCUS, 5)

'Bring up the common dialog box for opening files WMenuSelect("&File\&Open...") CurrentWindow = WFndWndWaitC("Open", "#32770", FW_FOCUS, 5)

'specify the file to open. You may need to change the path to the file WEditSetText (_id(&h480), "\msdev\vt4setup\readvt4.wri") Sleep 1

'obtain the handle of the Open command button hwndButton = WButtonFind("&Open")

'store timer information for purposes of performance measurements Timer1 = Timer

'set up a loop to detect when the line length of the edit box is no  'longer zero; that is, when Wordpad has finished the task of opening and 'formatting the file WButtonClick (_hwnd(hwndButton)) While WEditLineLen(_hwnd(TextWindow),1) = 0 Wend

Print "Elapsed time until task was completed: " + Str$(Timer - Timer1) WMenuSelect("&File\E&xit")  Run the script. Test will loop until Wordpad has finished opening and formatting the file. At that point, Test will print the amount of time it took for the task to complete.

Detecting Window Creation and Destruction
The following example simultaneously demonstrates detecting Window creation and destruction by using notifications and by using WFndWndC to determine when a task has completed.

  Insert the following text into a new Window: '$include 'declares' Dim Timer1 as Double Timer1 = Timer Dim hwnd as HWND

Sub WindowCreateHandler(vtNofityData as Variant) Print GetText(vtNotifyData) Print "Windowcreate handler" End Sub

Sub WindowDestroyHandler(vtNotifyData as Variant) Print "Windowdestroy handler" End Sub

'turn on WindowCreate notification On WindowCreate ("+Notepad",NULL) Call WindowCreateHandler

'wait until window is created - open Notepad after 5 seconds While WFndWndC("Notepad", "Notepad", FW_PART or FW_NOEXIST, 1) = -1 if (Timer - Timer1 > 5.0) then Run "Notepad.exe", NoWait end if     Sleep 1 Wend Print "Elapsed time until Window was created: " + Str$(Timer - timer1)

hwnd = WFndWndC("Notepad", "Notepad", FW_PART or FW_EXIST, 1) 'turn on WindowDestroy notification On WindowDestroy(hwnd) Call WindowDestroyHandler

Timer1 = Timer 'wait until window is destroyed - close Notepad after 5 seconds While WFndWndC("Notepad", "Notepad", FW_PART or FW_EXIST, 1) if (Timer - Timer1 > 5.0) then WMenuSelect("&File\E&xit") end if     Sleep 1 Wend Print "Elapsed time until Window was destroyed: " + Str$(Timer - timer1)  Run the script.

Detecting Graphical Changes to the UI
This example uses the text contained on the status bar of the Windows 95 WordPad program. The Window Information Utility identifies the status bar as a control with the class name AfxControlBar. Although it is a control, it does have text that can be obtained using the GetText function for demonstration purposes, the change in the text is detected by using the Screen library functions.

  Insert the following code into a new Window: '$include 'declares.inc'

Dim ScnReturnCode as integer Dim CurrentWindow as HWND Dim hwndButton as HWND Dim Timer1 as double Dim CurSrnReg As RECT, f$

CurSrnReg.wLeft = 3 CurSrnReg.wTop = 554 CurSrnReg.wRight = 94 CurSrnReg.wBottom = 568 f$ = "TEST.SCN"

'note you may need to change the path to Wordpad Run "c:\program files\accessories\Wordpad.exe", NoWait Sleep 2 CurrentWindow = WFndWndC("WordPad", "WordPadClass", FW_MAXIMIZE, 1)

ScnCaptureScreen (f$, "Screen1", CurSrnReg, FALSE)

'Bring up the common dialog box for opening files WMenuSelect("&File\&Open...") CurrentWindow = WFndWndWaitC("Open", "#32770", FW_FOCUS, 5)

'specify file to open. You may need to change the path to the file WEditSetText( _id(&h480), "d:\msdev\vt4setup\readvt4.wri" ) Sleep 1

'obtain the handle of the Open command button hwndButton = WButtonFind("&Open")

'store timer information for purposes of performance measurements ScnReturnCode = TRUE Timer1 = Timer

WButtonClick (_hwnd(hwndButton)) While (ScnReturnCode) ScnCaptureScreen (f$, "Screen2", CurSrnReg, FALSE) ScnReturnCode = ScnCompFiles (f$, "Screen1", f$, "Screen2", TRUE) Sleep 1 Wend

Print "Elapsed time until task was completed: " + Str$(Timer - Timer1) WMenuSelect("&File\E&xit")  Run the script.</li>  Create more efficient and compact code by using the ScnWaitForScreenMatch function. Replace the While loop with the following code, and run the script again: WButtonClick (_hwnd(hwndButton)) ScnWaitForScreenMatch(f$,"Screen1",CurSrnReg, FALSE,FALSE,1000,10) </li></ol>

Using the WaitUntilIdle function
The WaitUntilIdle function suspend the test case file until the foreground application becomes idle. This function relies on the MS-DOS Idle interrupt (INT 28h) to detect when an application becomes idle. Be cautious in implementing this function in test case files. You need to be aware of other components running on your system that may prevent the Windows Kernel module from getting into its idle loop and issuing an INT 28h. Currently, there are no known issues to prevent the successful use of this function under 32-bit operating systems. However, Microsoft recommends that you use the other techniques discussed in this article instead.

CAUTION: Do not use WaitUntilIdle as a common method for solving all of your timing-related problems. For example, the need to suspend a script for 5-10 seconds until a dialog box appears would not warrant the use of WaitUntilIdle.

The following code was taken directly from the Help file:

'$include 'declares' OPTION INTEGER DIM fIdle%, TimerStart&

Do

SetNotIdle TimerStart = Timer ' Wait up to 5 seconds for windows to go idle. fIdle = WaitUntilIdle (5000) If fIdle Then Print "Windows went idle in:"; Timer - TimerStart; "milliseconds" Else Print "Windows did not go idle in the specified amount of time, 5 seconds"

End End If Loop While TRUE