Search code examples
delphidependenciespackagedelphi-2007

How to get a list of all packages required by another package


My application uses runtime packages and I would like to get a list of all packages that are required by one of these.

Example:

PackA.bpl requires PackB.bpl and PackC.bpl.

How can I get packages required from PackA.bpl at runtime? (In this example, they would be PackB.bpl and PackC.bpl)


Solution

  • You can use GetPackageInfo from SysUtils. Here is an example of using it to enumerate list of units compiled in a package (in your case, in your callback check for ntRequiresPackage instead). For example:

    procedure GetRequiredPackageName(const Name: string; NameType: TNameType; Flags: Byte; Param: Pointer);
    var
      Names: TStrings absolute Param;
    begin
      case NameType of
        ntRequiresPackage:
          Names.Add(Name);
      end;
    end;
    
    procedure GetRequiredPackageNames(Module: HMODULE; Names: TStrings);
    var
      Flags: Integer;
    begin
      Names.BeginUpdate;
      try
        GetPackageInfo(Module, Names, Flags, GetRequiredPackageName);
      finally
        Names.EndUpdate;
      end;
    end;
    
    function ListRequiredPackages(HInstance: NativeInt; Data: Pointer): Boolean;
    var
      Names: TStrings absolute Data;
      I: Integer;
    begin
      Result := True;
      Names.Clear;
      GetRequiredPackageNames(HInstance, Data);
      Writeln(Format('%s requires: %d packages', [ExtractFileName(GetModuleName(HInstance)), Names.Count]));
      if Names.Count > 0 then
        for I := 0 to Names.Count - 1 do
          Writeln(Names[I]);
    end;
    
    procedure Main;
    var
      Names: TStringList;
      I: Integer;
    begin
      Names := TStringList.Create;
      try
        EnumModules(ListRequiredPackages, Names);
        Readln;
      finally
        Names.Free;
      end;
    end;
    

    To get the handle of a package by name, you can use GetModuleHandle:

    ListRequiredPackages(GetModuleHandle('PackA.bpl'), Names);