dum*_*uch 14 delphi delphi-2007
我希望能够确定某个特定单元是否已编译成Delphi程序,例如,单元SomeUnitName是我的某些程序的一部分而不是其他程序的一部分.我想有一个功能
function IsSomeUnitNameInProgram: boolean;
Run Code Online (Sandbox Code Playgroud)
(当然不会在SomeUnitName中声明,因为在这种情况下它将始终被包含),如果单元已编译到程序中,则在运行时返回true,否则返回false.
到目前为止,我的想法是使用jcl调试信息(从详细的映射文件编译),我基本上添加到我的所有程序来确定这些信息,但我更喜欢它,如果不需要jcl.
添加代码到SomeUnitName不是一个选项.
目前适用于Delphi 2007,但最好也适用于Delphi XE2.
有什么想法吗?
@DavidHeffernan问道:@DavidHeffernan问:
这不仅适用于一个程序,而且适用于100多个不同的程序.其中大部分都是在内部使用,但也有一些是交付给客户的.由于我们使用了相当多的库,有些在各种开源许可下购买了其他库,我希望能够在about框中添加一个"信用"选项卡,它只显示实际编译到程序中的库而不是所有库.感谢TOndrej的回答,现在完全符合我的要求:代码检查一个单元,如果程序使用了库,它总是链接的,如果它在那里,它会添加库名,版权和链接到about框.
Ond*_*lle 19
单元名称被编译到'PACKAGEINFO'资源中,您可以在其中查找:
uses
SysUtils;
type
PUnitInfo = ^TUnitInfo;
TUnitInfo = record
UnitName: string;
Found: PBoolean;
end;
procedure HasUnitProc(const Name: string; NameType: TNameType; Flags: Byte; Param: Pointer);
begin
case NameType of
ntContainsUnit:
with PUnitInfo(Param)^ do
if SameText(Name, UnitName) then
Found^ := True;
end;
end;
function IsUnitCompiledIn(Module: HMODULE; const UnitName: string): Boolean;
var
Info: TUnitInfo;
Flags: Integer;
begin
Result := False;
Info.UnitName := UnitName;
Info.Found := @Result;
GetPackageInfo(Module, @Info, Flags, HasUnitProc);
end;
Run Code Online (Sandbox Code Playgroud)
为当前可执行文件执行此操作传递它HInstance:
HasActiveX := IsUnitCompiledIn(HInstance, 'ActiveX');
Run Code Online (Sandbox Code Playgroud)
(GetPackageInfo枚举所有可能对包含许多单元的可执行文件效率低下的单元,在这种情况下,您可以在SysUtils中剖析实现并编写自己的版本,在找到单元时停止枚举.)
此函数将返回应用程序中包含的单元名称列表.适用于Delphi 2010.未经其他编译器验证.
function UnitNames: TStrings;
var
Lib: PLibModule;
DeDupedLibs: TList<cardinal>;
TypeInfo: PPackageTypeInfo;
PInfo: GetPackageInfoTable;
LibInst: Cardinal;
u: Integer;
s: string;
s8: UTF8String;
len: Integer;
P: PByte;
begin
result := TStringList.Create;
DeDupedLibs := TList<cardinal>.Create;
Lib := LibModuleList;
try
while assigned( Lib) do
begin
LibInst := Lib^.Instance;
Typeinfo := Lib^.TypeInfo;
if not assigned( TypeInfo) then
begin
PInfo := GetProcAddress( LibInst, '@GetPackageInfoTable');
if assigned( PInfo) then
TypeInfo := @PInfo^.TypeInfo;
end;
if (not assigned( TypeInfo)) or (DeDupedLibs.IndexOf( LibInst) <> -1) then continue;
DeDupedLibs.Add( LibInst);
P := Pointer( TypeInfo^.UnitNames);
for u := 0 to TypeInfo^.UnitCount - 1 do
begin
len := P^;
SetLength( s8, len);
if len = 0 then Break;
Inc( P, 1);
Move( P^, s8[1], len);
Inc( P, len);
s := UTF8ToString( s8);
if Result.IndexOf( s) = -1 then
Result.Add( s)
end
end
finally
DeDupedLibs.Free
end
end;
Run Code Online (Sandbox Code Playgroud)
在问题中建议使用的示例...
function IsSomeUnitNameInProgram: boolean;
var
UnitNamesStrs: TStrings;
begin
UnitNamesStrs := UnitNames;
result := UnitNamesStrs.IndexOf('MyUnitName') <> -1;
UnitNamesStrs.Free
end;
Run Code Online (Sandbox Code Playgroud)