Description
Before calling a routine from a DLL, you must define the routine type in TestComplete. DefineProc
registers the routine type in TestComplete. Note that the DLL
object can call only the routines of the stdcall
type. (This type is used by Windows API functions).
Note: | If the DLL was built with debug information, there is no need to define the routine type manually. TestComplete takes information on the routine type from the debug information in this case. |
Declaration
IDefineDLLObj.DefineProc(ProcName, type1, type2, ..., typeN, ResType)
IDefineDLLObj | An expression, variable or parameter that specifies a reference to an IDefineDLL object | |||
ProcName | [in] | Required | String | |
type1 | [in] | Optional | Integer | |
type2 | [in] | Optional | Integer | ... |
typeN | [in] | Optional | Integer | |
ResType | [in] | Required | Integer | |
Result | None |
Applies To
The method is applied to the following object:
Parameters
The method has the following parameters:
ProcName
The routine name as it is declared in the desired DLL. For instance, if you want to call the GetWindowText
function from the User32.dll, you should use GetWindowTextA
or GetWindowTextW
, but not GetWindowText
. (However, you can call GetWindowTextA
as GetWindowText
. For this purpose, you need to create an alias for this function. See IDefineDLL.DefineAlias
.)
type1, type2, ..., typeN
Specify data types of the first, second, third, etc. function parameters. They can be one of the constants built in TestComplete or an ID created by the DLL.DefineType
or IDLLAccessProcess.DefineType
method.
Make sure that you correctly specified the types of the parameters. Specifying incorrect data types in a DLL function’s definition may later cause TestComplete to shut down when calling the function from tests (this happens because erroneous definitions may cause incorrect stack processing). |
ResType
The type of the value returned by the function. It can be one of the constants built in TestComplete or an ID generated by DLL.DefineType
(or IDLLAccessProcess.DefineType
). This parameter is required, and it must always be specified. If a routine does not return any value, ResType must be either vt_empty
or vt_void
.
TestComplete cannot receive string values returned as the results from a DLL function. If a function returns a string value (for instance, a char* or wchar_t* value in Visual C++, or an AnsiString or WideString value in Delphi), you will not be able to obtain the function’s result in your test.
Note for Delphi users: the |
Result Value
None.
Remarks
-
If the method registers a routine that was registered earlier in the current test or in the previous test (if the
ClearSettingsBeforeEachRun
option is enabled), it posts a warning message to the test log. -
The purpose of specifying data types is to let TestComplete know the size of memory blocks it should reserve to hold values of structure members and how it should interpret routine parameters and push them to the stack, etc. As the type size can differ from one compiler to another or even between two versions of the same compiler, it is recommended that you refer to the compiler documentation to learn the type size.
-
Most compilers can align structure members at certain addresses multiple by 1, 2, 4 or more bytes. For instance, often an application uses the double word alignment (4 bytes). In this case the address of each member is a multiple of four. So, if a structure has a boolean member, you should specify its type as
vt_b4
instead ofvt_b1
. TestComplete does not align structure members itself.By default, compilers use alignment for those structures that are defined by default, that is, without the use of the
#pragma pack(...)
statement in C++ code orpacked record
in Delphi. When creating a data type for the “default” structures in scripts, pay attention to the size of the structure members. -
For JavaScript, JScript, Python, C#Script and C++Script users: These scripting languages do not support passing variables by references through parameters of a function being called. Therefore, you cannot pass a variable of an ordinary data type (like integer, boolean, etc.) by a reference to a DLL routine and get the value modified by the routine in your JavaScript, JScript, Python, C#Script or C++Script (this restriction applies to C#Script and C++Script too since these languages are based on JScript and use the JScript engine) test. In this case, the value of the variable passed to the DLL routine from your JavaScript, JScript, Python, C#Script or C++Script test actually remains the same after the routine execution is over because the routine works with a copy of the variable.
However, objects are passed through routine parameters by references in these languages, and if the callee routine modifies some members of an object passed through its parameters, the caller routine can access the updated object. Therefore, if you pass a custom structure, array or string value created by the
DLL.New
orIDLLAccessProcess.New
method (see Using Custom Data Structures in DLL Function Calls, Using Arrays in DLL Function Calls and Using String Parameters in DLL Function Calls) from your JavaScript, JScript, Python, C#Script or C++Script test to a DLL routine, you can then access the modified structure, array or string after the routine execution is over. The point is that such structures, arrays and strings are created by theNew
methods as wrapper objects and such objects passed to a DLL routine can be modified and returned from the routine to which they are passed by references.
Constants
The following table lists the constants you use to define data types. You can find examples below and in the Parameter Types for C++ Routines and Structures and Parameter Types for Delphi Routines and Structures topics. These constants are also used in the
DLL.DefineType
and IDLLAccessProcess.DefineType
methods where they specify the types of structure members.
Constant | Description |
---|---|
vt_b1 |
One-byte boolean. True = -1, False = 0. |
vt_b2 |
2-byte boolean. True = -1, False = 0. |
vt_b4 |
4-byte boolean. True = -1, False = 0. |
vt_bool |
4-byte boolean. True = -1, False = 0.
|
vt_bstr |
BSTR. OLE Automation string type. |
vt_byref |
JavaScript, JScript vt_byref | vt_i4 Python vt_byref | vt_i4 VBScript vt_byref or vt_i4 DelphiScript vt_byref or vt_i4 C++Script, C#Script vt_byref | vt_i4 |
vt_clsid |
CLSID, GUID. |
vt_cy |
Currency (8 bytes). |
vt_date |
Date. |
vt_dispatch |
|
vt_empty |
Empty value.
|
vt_error |
SCODE values. |
vt_hresult |
Standard return type. Normally, |
vt_i1 |
Signed char (one byte). |
vt_i2 |
2-byte signed integer. |
vt_i4 |
4-byte signed integer. |
vt_i8 |
8-byte signed integer. |
vt_int |
Signed machine integer (4 bytes). |
vt_lpstr |
Null-terminated string. |
vt_lpwstr |
Null terminated wide-string. |
vt_r4 |
4-byte float. |
vt_r8 |
8-byte float. |
vt_ui1 |
Unsigned char (one byte). |
vt_ui2 |
Unsigned short integer (2 bytes). |
vt_ui4 |
Unsigned integer (4 bytes). |
vt_ui8 |
Unsigned integer (8 bytes). |
vt_uint |
Unsigned machine integer (4 bytes). |
vt_variant |
VARIANT type (16 bytes). |
vt_void |
The C void type. |
Example
The code below defines the GetWindowText procedure, then creates an alias for this procedure and calls it from script using the created alias.
JavaScript, JScript
function DefineProcDemo()
{
// Defines the DLL type
var DefDLL = DLL.DefineDLL("user32");
// Loads the DLL in memory
var Lib = DLL.Load("C:\\Windows\\System32\\user32.dll");
// Defines the procedure
DefDLL.DefineProc("GetWindowTextA", VT_UI4, VT_LPSTR, VT_I4, VT_I4);
// ...
// Creates an alias for the procedure
DefDLL.DefineAlias("GetWindowText", "GetWindowTextA");
// ...
var hndl = Sys.Process("Notepad").Window("Notepad").Handle;
var winText = DLL.New("LPSTR", 256);
// Calls the routine using the alias
Lib.GetWindowText(hndl, winText, 20);
Log.Message(winText)
}
Python
def DefineProcDemo():
# Defines the DLL type
DefDLL = DLL.DefineDLL("user32")
# Loads the DLL in memory
Lib = DLL.Load("C:\\Windows\\System32\\user32.dll")
# Defines the procedure
DefDLL.DefineProc("GetWindowTextA", VT_UI4, VT_LPSTR, VT_I4, VT_I4)
# ...
# Creates an alias for the procedure
DefDLL.DefineAlias("GetWindowText", "GetWindowTextA")
# ...
hndl = Sys.Process("Notepad").Window("Notepad").Handle
winText = DLL.New("LPSTR", 256)
# Calls the routine using the alias
Lib.GetWindowText(hndl, winText, 20)
Log.Message(winText)
VBScript
Sub DefineProcDemo
' Defines the DLL type
Set DefDLL = DLL.DefineDLL("user32")
' Loads the DLL in memory
Set Lib = DLL.Load("C:\Windows\System32\user32.dll")
' Defines the procedure
Call DefDLL.DefineProc("GetWindowTextA", VT_UI4, VT_LPSTR, VT_I4, VT_I4)
' ...
' Creates an alias for the procedure
Call DefDLL.DefineAlias("GetWindowText", "GetWindowTextA")
' ...
hndl = Sys.Process("Notepad").Window("Notepad").Handle
Set winText = DLL.New("LPSTR", 256)
' Calls the routine using the alias
Call Lib.GetWindowText(hndl, winText, 20)
Call Log.Message(winText)
End Sub
DelphiScript
procedure DefineProcDemo;
var DefDLL, Lib, hndl, winText;
begin
// Defines the DLL type
DefDLL := DLL.DefineDLL('user32');
// Loads the DLL in memory
Lib := DLL.Load('C:\Windows\System32\user32.dll');
// Defines the procedure
DefDLL.DefineProc('GetWindowTextA', VT_UI4, VT_LPSTR, VT_I4, VT_I4);
// ...
// Creates an alias for the procedure
DefDLL.DefineAlias('GetWindowText', 'GetWindowTextA');
// ...
hndl := Sys.Process('Notepad').Window('Notepad').Handle;
winText := DLL.New('LPSTR', 256);
// Calls the routine using the alias
Lib.GetWindowText(hndl, winText, 20);
Log.Message(winText);
end;
C++Script, C#Script
function DefineProcDemo()
{
// Defines the DLL type
var DefDLL = DLL["DefineDLL"]("user32");
// Loads the DLL in memory
var Lib = DLL["Load"]("C:\\Windows\\System32\\user32.dll");
// Defines the procedure
DefDLL["DefineProc"]("GetWindowTextA", VT_UI4, VT_LPSTR, VT_I4, VT_I4);
// ...
// Creates an alias for the procedure
DefDLL["DefineAlias"]( "GetWindowText", "GetWindowTextA" );
// ...
var hndl = Sys["Process"]("Notepad")["Window"]("Notepad")["Handle"];
var winText = DLL["New"]("LPSTR", 256);
// Calls the routine using the alias
Lib["GetWindowText"](hndl, winText, 20);
Log["Message"](winText)
}
See Also
Calling DLL Functions From Tests - Tutorial
Parameter Types for C++ Routines and Structures
Parameter Types for Delphi Routines and Structures
DefineAlias Method
DLL Object
IDLLAccessProcess Object