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.

  1. 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")
    
    

  2. 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.

  1. 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)
    
    

  2. 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.

  1. 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")
    
    

  2. Run the script.

  3. 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)

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


Additional reference words: 4.00 Win32
KBCategory: kbusage kbwebcontent
KBSubCategory:


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 25, 1996
©1997 Microsoft Corporation. All rights reserved. Legal Notices.