I wrote a DLL in Delphi 10.1 that uses Devart IBDac components to allow backup and restore of a Firebird DB within the installation (upgrade of an application from Firebird 1.5 to 3). With Ansi Inno Setup 5.5.9 everything worked fine. As I wanted to avoid AnsiString
and PAnsiChar
as parameters (for more convenient use from Delphi) I installed Inno Setup Unicode version 5.5.9(u) and changed the parameters from AnsiString
/PAnsiChar
to String
in the DLL and also in the Inno Setup Script. I also tried WideString
in the Inno Setup script but this didn't work at all. PChar
is not recognized by Inno Setup.
The strange thing is that the script partly works, the parameters are correctly transferred to the DLL but I experience GPFs in situations that have nothing to do with the parameters:
- Using trim on a string within the DLL (no parameter!) creates a GPF.
- Creating a DBConnection-Object creates a GPF too.
I think the parameter-types are root of this evil. That is the only thing I changed in DLL and script. The versions with AnsiString
still work well.
Thanks for sharing any ideas about, what I am doing wrong here.
Update: Example Code as requested:
Delphi procedure that runs a script from a resource, fails in the very first statement. With MessageBox
in the first line I verified that all parameters arrive correctly.
procedure runScript(aServer, aDatabase, aUser, aPW, aPort, DLL, script: String); stdcall;
var
ResStream: TResourceStream;
DB: TIBCConnection;
SC: TIBCScript;
{ Muss Ansistring sein wegen Resourcestream }
s: ansistring;
begin
try
DB := TIBCConnection.create(nil);
SC := TIBCScript.create(nil);
SC.Connection := DB;
try
DB.clientlibrary := DLL;
DB.Database := aDatabase;
DB.Server := aServer;
DB.Username := aUser;
DB.Password := aPW;
DB.Port := aPort;
DB.connected := true;
ResStream := TResourceStream.create(hInstance, script, RT_RCDATA);
setlength(s, ResStream.size);
ResStream.ReadBuffer(s[1], ResStream.size);
SC.SQL.Text := String(s);
SC.Execute;
DB.close;
finally
SC.free;
DB.free;
end;
except
on e: Exception do
begin
MessageBox(0, PChar(e.message), PChar('Setup - Fehler in "' + script + '"'), mb_ok);
raise;
end;
end;
end;
Definition of the procedure in Inno Setup (Unicode). Other required DLLs are declared in the first function definition so they are all present. It works with AnsiString
/PAnsiChar
!
procedure runScript(aServer, aDatabase, aUser, aPW, aPort, DLL, script: String);
external 'runScript@files:itcsetupfb.dll stdcall setuponly';
This restore function works but only if I do not use TRIM() within the function:
procedure restoreDB(destServer, destDatabase, destSysdbaPW, aBackupfile, aPort, DLL: String; PBRange: integer;
PbHandle, LblHandle, WizHandle: THandle); stdcall;
var
IBCRestoreService1: TIBCRestoreService;
cnt: integer;
s: String;
Msg: TMsg;
begin
IBCRestoreService1 := TIBCRestoreService.create(nil);
SendMessage(PbHandle, PBM_SETRANGE, 0, PBRange shl 16);
cnt := 0;
try
try
with IBCRestoreService1 do
begin
clientlibrary := DLL;
Database.Text := destDatabase;
Server := destServer;
Username := 'sysdba';
Password := destSysdbaPW;
Port := aPort;
Options := [roFixFssMetadata, roNoValidityCheck, roFixFssData, roOneRelationAtATime, roDeactivateIndexes];
FixFssCharset := 'ISO8859_1';
BackupFile.Text := aBackupfile;
PageSize := 16384;
verbose := true;
Attach;
try
ServiceStart;
while IsServiceRunning do
begin
inc(cnt);
if cnt > PBRange then
cnt := 0;
s := GetNextLine + ' ';
{ this was formerly s:=trim(strinGreplace(s,'gbak:','', }
{ [rfReplaceall,rfIgnoreCase])). I Identified the trim to be the }
{ cause of the GPF. Very strange. }
delete(s, 1, 5);
while (length(s) > 0) and (s[1] = #32) do
delete(s, 1, 1);
{ if we have no message file (local fb15) }
if pos('format message', s) > 0 then
s := 'Arbeite ...';
SendMessage(LblHandle, $0C, 0, longint(s));
SendMessage(PbHandle, PBM_SETPOS, cnt, 0);
while PeekMessage(Msg, WizHandle, 0, 0, PM_REMOVE) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
UpdateWindow(PbHandle);
end;
finally
detach;
end;
end;
finally
IBCRestoreService1.free;
end;
except
on e: Exception do
begin
MessageBox(0,
PChar('Die Wiederherstellung der EMILpro Datenbank ist leider fehlgeschlagen. Folgender Fehler trat auf: ' +
#13#10#10 + e.message), 'Setup - Fehler bei Wiederherstellung', mb_ok);
raise;
end;
end;
end;
This function is declared in Inno Setup like this:
procedure restoreDB(destServer, destDatabase, destSysdbaPW, aBackupfile, aPort, DLL: String;
PBRange: integer; PbHandle,LblHandle,WizHandle: THandle);
external 'restoreDB@files:itcsetupfb.dll,fbclient.dll,gds32.dll,icudt52.dll,icudt52l.dat,icuin52.dll,icuuc52.dll,fbintl.dll,firebird.conf,firebird.msg,ib_util.dll,engine12.dll,msvcp100.dll,msvcr100.dll,fbintl.conf stdcall setuponly';