Tuesday, December 18, 2007

Reading Info From a Package

If you've ever wanted to find out what packages a package depends on (without using tdump.exe), or implicit units a package has or the units the package contains, then take a look at the code below.


program pdump;

{$APPTYPE CONSOLE}

uses
SysUtils,
Classes;

var
RequiresList: TStrings;
ImplicitUnits: TStrings;
ContainsList: TStrings;

procedure PackageInfoProc(const Name: string;
NameType: TNameType; Flags: Byte;
Param: Pointer);
begin
if NameType = ntContainsUnit then
begin
ContainsList.Add(Name);

if (Flags and $10 <> 0) and (Flags and $06 = 0) then
ImplicitUnits.Add(Name);
end
else if NameType = ntRequiresPackage then
RequiresList.Add(Name);
end;

procedure WriteStrings(Strings: TStrings);
var
Index: Integer;
begin
for Index := 0 to Strings.Count - 1 do
WriteLn(Strings[Index]);
end;

var
Module: HMODULE;
Flags: Longint;
begin
RequiresList := TStringList.Create;
ImplicitUnits := TStringList.Create;
ContainsList := TStringList.Create;

Module := LoadPackage(ParamStr(1));

try
if Module <> 0 then
begin
GetPackageInfo(Module, nil, Flags, PackageInfoProc);

WriteLn('Requires List');
WriteStrings(RequiresList);
WriteLn(#13#10 + 'Implicit Uses');
WriteStrings(ImplicitUnits);
WriteLn(#13#10 + 'Contains List');
WriteStrings(ContainsList);
end;
finally
UnloadPackage(Module);
RequiresList.Free;
ImplicitUnits.Free;
ContainsList.Free;
end;
end.

4 comments:

Allen said...

This will only work if the package in question can also load all the dependent packages. When that is not the case, it is better to simply call LoadLibraryEx() with the LOAD_LIBRARY_AS_DATAFILE flag. This will load *only* that package and not resolve any dependencies or do any fixups.

Rob Kennedy said...

Interesting. Any explanation of what those flags mean?

Allen said...

Look at the source in SysUtils.pas. There are many comments down around the CheckForDuplicateUnits function.

Fishous said...

I don't know about you, but for me the procedure implementation line is cut off right after "Flags:", like this:

procedure PackageInfoProc(const Name: string; NameType: TNameType; Flags:

Post a Comment