edsynergy wrote:
> Here is a small function that extracts a string from a resource dll.
> Works fine when the resource is there, and I get an EResNotFound When
> one is not found. However when the code in the exception clause is run
> (on EResNotFound do Result:= blank;) it immetiately gives an AV. In
> fact it dos'nt matter what code I put in the exception I get the AV
> I cant see what the problem is
>
> Best wishe Ed.
>
> function TformMainTasks.SetAnchorText(const ResString:string):string;
> var
> ls:Tstringlist;
> ms:TresourceStream;
> h:Thandle;
> begin
>
> try
> h := LoadLibrary(pchar('strings.dll'));
Do not type-cast a string literal to PChar. The compiler already
recognizes when a PChar is required. It only needs a hint like that when
overload resolution might pick the wrong function. LoadLibrary isn't
overloaded.
> try
> ms:=TresourceStream.Create(h,ResString, RT_RCDATA);
> if ( Assigned(ms)) then
That conditional will never fail. The constructor of a class will never
return nil. If there is a problem allocating an object, you'll get an
exception, in which case no value gets assigned to the variable at all.
> begin
> try
> ls:= TstringList.Create;
> ms.Position:= 0;
> ls.LoadFromStream(ms);
> Result:= ls.Text;
> finally
> ls.Free;
> // free resources
> end; // try/finally
> End
> Else Result:= blank;
> except
> on EResNotFound do Result:= blank;
> end; // try/except
> finally
> ms.Free;
> FreeLibrary(h);
>
> // free resources
> end; // try/finally
Never ignore a compiler warning. In your code, you should have gotten
warnings in the "finally" blocks suggesting that ls, ms, and h might not
be initialized. The problem stems from misusing the try-finally block. A
try-finally sequence should always have this structure:
AcquireResource;
try
UseResource;
finally
ReleaseResource;
end;
In your code, you enter the try-finally block and *then* you acquire a
handle to the DLL, and it's even later before you acquire a
TResourceStream object. You mustn't enter a try-finally block until
you've successfully acquired the thing that the try-finally block is
meant to protect.
Try this code instead:
function TFormMainTasks.SetAnchorText(const ResString: string): string;
var
ls: TStringList;
ms: TResourceStream;
h: THandle;
begin
h := LoadLibrary('strings.dll');
Win32Check(h <> 0);
try
try
ms := TResourceStream.Create(h, ResString, RT_RCDATA);
try
ls := TStringList.Create;
try
ls.LoadFromStream(ms);
Result := ls.Text;
finally
ls.Free;
end;
finally
ms.Free;
end;
except
on EResNotFound do
Result := blank;
end;
finally
FreeLibrary(h);
end;
end;
--
Rob