Moin Zusammen,
im Zusammenhang mit dem Auslesen von Resourcen bin ich gerade auf ein Problem gestossen.
Ich erzeuge mir eine Dateiliste (mit Pfaden) die ich dann in einer Schleife durchgehe, um mir die enthaltenen Resourcentypen und Namen herauszusammeln.
Als Ergebnis habe ich dann einen TreeView, in dem auf der obersten Ebene die Nodes als Text den Pfad der Datei haben, in der darunterliegenden Ebene die Resourcentypen, und unter diesen dann die Resourcennamen.
Das klappt auch soweit.
Jetzt wollte ich mir für den Typ RT_STRING auch jeweils gleich die Werte auslesen, und bin da auf ein Problem gestossen.
Durchgehen durch die Dateiliste:
Delphi-Quellcode:
procedure ExtractResourceInfo(const p_slFileList : TStringList;const p_tvRoot : TTreeView);
var
i : integer;
hFile : DWORD;
tnWork : TTreeNode;
begin
for i := 0 to p_slFileList.Count-1 do
begin
Application.ProcessMessages;
hFile := LoadLibraryEx(PChar(p_slFileList[i]),0,LOAD_LIBRARY_AS_DATAFILE);
try
if (hFile <> 0) then
begin
tnWork := p_tvRoot.Items.Add(nil,p_slFileList[i]);
EnumResourceTypes(hFile,@BuildResourceTypeList,integer(tnWork));
end;
finally
if hFile <> 0 then
begin
FreeLibrary(hFile);
end;
end;
end;
end;
Callback Funktion EnumResTypeProc
Delphi-Quellcode:
function BuildResourceTypeList(const p_hFile : DWORD;const p_pszType : PChar;p_pLParam : TTreeNode) : Boolean; stdcall;
const
RT_HTML = MAKEINTRESOURCE(23);
RT_MANIFEST = MAKEINTRESOURCE(24);
var
tnWork : TTreeNode;
sType : string;
begin
if IS_INTRESOURCE(integer(p_pszType)) then
begin
case integer(p_pszType) of
integer(RT_ACCELERATOR) : sType := 'RT_ACCELERATOR';
integer(RT_ANICURSOR) : sType := 'RT_ANICURSOR';
integer(RT_ANIICON) : sType := 'RT_ANIICON';
integer(RT_BITMAP) : sType := 'RT_BITMAP';
integer(RT_CURSOR) : sType := 'RT_CURSOR';
integer(RT_DIALOG) : sType := 'RT_DIALOG';
integer(RT_DLGINCLUDE) : sType := 'RT_DLGINCLUDE';
integer(RT_FONT) : sType := 'RT_FONT';
integer(RT_FONTDIR) : sType := 'RT_FONTDIR';
integer(RT_GROUP_CURSOR) : sType := 'RT_GROUP_CURSOR';
integer(RT_GROUP_ICON) : sType := 'RT_GROUP_ICON';
integer(RT_HTML) : sType := 'RT_HTML';
integer(RT_ICON) : sType := 'RT_ICON';
integer(RT_MANIFEST) : sType := 'RT_MANIFEST';
integer(RT_MENU) : sType := 'RT_MENU';
integer(RT_MESSAGETABLE) : sType := 'RT_MESSAGETABLE';
integer(RT_PLUGPLAY) : sType := 'RT_PLUGPLAY';
integer(RT_RCDATA) : sType := 'RT_RCDATA';
integer(RT_STRING) : sType := 'RT_STRING';
integer(RT_VERSION) : sType := 'RT_VERSION';
integer(RT_VXD) : sType := 'RT_VXD';
else
sType := '#'+IntToStr(integer(p_pszType));
end;
tnWork := TTreeView(p_pLParam.TreeView).Items.AddChild(p_pLParam,sType);
EnumResourceNames(p_hFile,p_pszType,@BuildResourceNameTable,integer(tnWork));
end
else
begin
sType := trim(p_pszType);
tnWork := TTreeView(p_pLParam.TreeView).Items.AddChild(p_pLParam,sType);
EnumResourceNames(p_hFile,PChar(sType),@BuildResourceNameTable,integer(tnWork));
end;
Result := true;
end;
Callback Funktion EnumResNameProc
Delphi-Quellcode:
function BuildResourceNameTable(const p_hFile : DWORD;const p_pszType : PChar;const p_pszName : PChar;const p_pLParam : TTreeNode) : Boolean; stdcall;
var
sName : string;
szBuffer : PChar;
begin
if IS_INTRESOURCE(integer(p_pszName)) then
begin
sName := '#'+IntToStr(integer(p_pszName));
end
else
begin
sName := trim(p_pszName);
end;
if p_pszType = RT_STRING then
begin
if p_hFile <> 0 then
begin
szBuffer := StrAlloc(65536);
try
// [color=red]Hier schlägt's fehl mit der Meldung, dass die angegebene Resource nicht gefunden werden konnte[/color]
if LoadString(p_hFile,integer(p_pszName),szBuffer,65535) <> 0 then
begin
sName := sName + ' / '+trim(szBuffer);
end
else
begin
sName := sName + ' / '+SysErrorMessage(GetLastError);
end;
finally
StrDispose(szBuffer);
end;
end;
end;
TTreeView(p_pLParam.TreeView).Items.AddChild(p_pLParam,sName);
Result := true;
end;
Als Paramter für die Resource habe ich es auch schon mit cardinal und PChar(sName) probiert (auch wenn letzteres ja eigentlich Unsinn ist).
Das Ergebnis war immer das gleiche.
Ausser z.B. bei der Kernel32 bei der die eine oder andere RT_STRING Resource ausgelesen wurde (ob korrekt oder nicht sei mal dahingestellt) kommt immer nur der Fehler, dass die Resource nicht gefunden wurde.
Interessant dabei: Es wurden nicht alle aus der Kernel32 ausgelesen, nur ein paar (vier um genau zu sein, nämlich 1, 2, 1025 und 1089).
Was auch noch auffiel:
Ich hatte es unmittelbar vor dem LoadString auch schon mal mit GetModuleHandle versucht um ein
Handle auf die geladene Datei zu bekommen. Dies schlug mit schöner Regelmässigkeit fehl mit der Meldung, dass das Modul nicht gefunden werden konnte. Da es aber über LoadLibraryEx geladen wurde (sonst wären ja die Enum Funktionen gar nicht aufgerufen worden) kann das irgendwie auch nicht sein, ausser LOAD_LIBRARY_AS_DATAFILE verhindert die erfolgreiche Suche von GetModuleHandle.
Wäre denkbar, denn bei Kernel32 schlug's nicht fehl, und die wird ja zu jedem Prozess geladen.
Hat irgendjemand 'ne Idee?
BTW: Getestet unter
W2K SP2