Friday, April 10, 2009

Handle allocated to Delphi Packages

We may seldom need to deal with Windows API when using Delphi VCL to develop a Win32 application. The most common information we may want to retrieve is the file name of the main executable in runtime. In this case, we use
MyExeFileName := ParamStr(0);
Delphi packages (.bpl) itself are a better windows .DLL. We may use it like normal windows .DLL file but it is more than that. Here are some useful tricks when work with dynamic packages.

HINSTANCE

HINSTANCE is a cardinal variable available at runtime. It will always return the module handle allocated by windows depends on where the current execution point is. For example, if current code is at the main .exe, the HINSTANCE will return handle of the .exe module. If current code is at .bpl package, the HINSTANCE will return handle of the .bpl package.

GetModuleHandle

You may use GetModuleHandle to retrieve the handle of known .exe or .bpl file name. For example,
hExe := GetModuleHandle(PAnsiChar('main.exe'))
will return the handle of main.exe module.
hBPL := GetModuleHandle(PAnsiChar('package.bpl'))
will return the handle of package.bpl package.

If we pass a NULL parameter to the function,
hNULL := GetModuleHandle(nil)
It will always return the handle of main executable even if current execution point is in a package. Thus, hNULL and hEXE should have same value.

You may now understand what is the value returned by LoadPackage and the value required by UnloadPackage. Both values are handle allocated by windows. So,
m := LoadPackage('package.dll');
hBPL := GetModuleHandle(PAnsiChar('package.dll'));
Assert(m = hBPL); // must be equal
UnloadPackage(bBPL);
To test if current execution point is at main executable, you may use
if HINSTANCE = GetModuleHandle(nil) then
// in main executable
else
// in a package or dll module

GetModuleName

GetModuleName(hEXE) will return the main executable file name. It should be same as ParamStr(0).

GetModuleName(hBPL) will return the package file name.

GetModuleName(HINSTANCE) will return the current module name (either Main executable or package) depends on where the current execution point is.

No comments: