Q.:
How can I close a modal dialog which was invoked by a method called from a script?
A.:
Generally a script instruction is not executed until the previous instruction is finished. This behavior causes unexpected pauses in test execution since routines that invoke modal dialogs return the resulting value only when the corresponding dialog is closed.
To solve this issue the Runner.CallObjectMethodAsync method was introduced in TestComplete ver. 4.2. It calls the specified object method asynchronously. That is, it does not wait for the method to complete, but proceeds to the next code instruction. Thus the further instructions can simulate the actions needed to close the dialog (typically press OK or Close button). To find out whether the previously called method had finished, the CallObjectMethodAsync returns an especial CallObjectMethodAsyncResult object. See the "Testing Modal Windows" help topic for details.
Below is an example that calls a dialog of an Open application and then closes it via user interface actions.
' Calls the method that displays a modal dialog
Set ResObject = Runner.CallObjectMethodAsync(p.VCLObject("MainForm")._
VCLObject("ADialog"), "Execute")
' Simulates user actions over the dialog and closes it
Set w = p.WaitWindow("*", " ADialogCaption ", -1, 1000)
w.Window("Button", "*Ok*").ClickButton()
Log.Message("The window was not found.")
' Waits for method completion
ResObject.WaitForCompletion(5000)
If ResObject.Completed Then
Log.Message("Success, Return Value: " + CStr(ResObject.ReturnValue))
Log.Message("Failure, Return Value: " + CStr(ResObject.ReturnValue))
// Calls the method that displays a modal dialog
ResObject = Runner.CallObjectMethodAsync(p.VCLObject("MainForm").
VCLObject("ADialog "), "Execute");
// Simulates user actions over the dialog and closes it
w = p.WaitWindow("*", " ADialogCaption", -1, 1000);
w.Window("Button", "*Ok*").ClickButton();
Log.Message("The window was not found.")
// Waits for method completion
ResObject.WaitForCompletion(5000);
Log.Message("Success, Return Value: " + ResObject.ReturnValue);
Log.Message("Failure, Return Value: " + ResObject.ReturnValue);
var p, w, ResObject: OleVariant;
// Calls the method that displays a modal dialog
ResObject := Runner.CallObjectMethodAsync(p.VCLObject('MainForm').
VCLObject('ADialog'), 'Execute');
// Simulates user actions over the dialog and closes it
w := p.WaitWindow('*', 'ADialogCaption', -1, 1000);
w.Window("Button", '*Ok*').ClickButton()
Log.Message('The window was not found.');
// Waits for method completion
ResObject.WaitForCompletion(5000);
if ResObject.Completed then
Log.Message('Success, Return Value: ' + VarToStr(ResObject.ReturnValue))
Log.Message('Failure, Return Value: ' + VarToStr(ResObject.ReturnValue));
// Calls the method that displays a modal dialog
ResObject = Runner["CallObjectMethodAsync"](p["VCLObject"]("MainForm")
["VCLObject"]("ADialog"), "Execute");
// Simulates user actions over the dialog and closes it
w = p["WaitWindow"]("*", "ADialogCaption", -1, 1000);
w["Window"]("Button", "*Ok*")["ClickButton"]();
Log["Message"]("The window was not found.")
// Waits for method completion
ResObject["WaitForCompletion"](5000);
if (ResObject["Completed"])
Log["Message"]("Success, Return Value: " + ResObject["ReturnValue"]);
Log["Message"]("Failure, Return Value: " + ResObject["ReturnValue"]);
However, it is not recommended to use the Runner.CallObjectMethodAsync method to perform asynchronous calls to methods provided by TestComplete. Some of the built-in methods may operate normally, while the others may cause problems when they are called asynchronously. Therefore certain TestComplete methods cannot be launched via CallObjectMethodAsync. An example of such a method is the BuiltIn.SendMAPIMail routine. It often invokes a security warning dialog displayed by Outlook / Outlook Express which cannot be closed by TestComplete.
The only solution is to close the dialog from another process, namely, via the Windows Script Host. This is a language-independent utility that introduces wide capabilities for automation. The helper script we are interested in should focus the dialog window and perform the actions needed to close the dialog.
Here is the code of a script that closes the Outlook Express security dialog. The code should be placed in a text file named CloseSecurityDialog.vbs
WindowCaption = "Outlook Express"
Set WshShell = WScript.CreateObject("WScript.Shell")
' Focus the dialog window
a = WshShell.AppActivate(WindowCaption)
a = WshShell.AppActivate(WindowCaption)
' Simulate the ALT+S keystroke that is an accelerator For the "Send" button
Once the helper Windows Script is created, you can call it from TestComplete right before the instruction that invokes the modal dialog. The following code snippet demonstrates how to do this:
' Obtain the OLE object of Windows Script Host
Set WshShell = Sys.OleObject("WScript.Shell")
' Launch the script at specified path
WshShell.Run("C:\Work\CloseSecurityDialog.vbs")
' Call the routine invoking a modal dialog
If SendMAPIMail("John Smith", "jsmith@domain.com", "MessageSubject", "MessageBody") Then
Log.Message("Mail was sent")
Log.Warning("Mail was not sent")
// Obtain the OLE object of Windows Script Host
WshShell = Sys.OleObject("WScript.Shell");
// Launch the script at specified path
WshShell.Run("C:\\Work\\CloseSecurityDialog.vbs");
// Call the routine invoking a modal dialog
if (SendMAPIMail("John Smith", "jsmith@domain.com", "MessageSubject", "MessageBody"))
Log.Message("Mail was sent");
Log.Warning("Mail was not sent");
function ModalMessager();
var WshShell : OleVariant;
// Obtain the OLE object of Windows Script Host
WshShell := Sys.OleObject('WScript.Shell');
// Launch the script at specified path
WshShell.Run('C:\Work\CloseSecurityDialog.vbs');
// Call the routine invoking a modal dialog
if (SendMAPIMail('John Smith', 'jsmith@domain.com', 'MessageSubject', 'MessageBody')) then
Log.Message('Mail was sent.')
Log.Warning('Mail was not sent.');
// Obtain the OLE object of Windows Script Host
WshShell = Sys["OleObject"]("WScript.Shell");
// Launch the script at specified path
WshShell["Run"]("C:\\Work\\CloseSecurityDialog.vbs");
// Call the routine invoking a modal dialog
if (SendMAPIMail("John Smith", "jsmith@domain.com", "MessageSubject", "MessageBody"))
Log["Message"]("Mail was sent");
Log["Warning"]("Mail was not sent");