I developed a tool using Firedac with the database as SQLite.
after finishing the project and making an installer (InnoSetup) I get an error
[FireDAC][Phys][SQLite] ERROR: unable to open database file
when I launch the app (double click).
This is the connection parameters I use
constructor TDbInteract.Create(const aDatabasePath: string; const aOnNeedCredentials: TOnNeedCredentials);
var
aParams: array of string;
begin
if not TFile.Exists(aDatabasePath) then
raise Exception.Create('Database file not found');
aParams := ['DriverID=SQLite',
'Database=' + aDatabasePath,
'OpenMode=CreateUTF16',
'LockingMode=Normal',
'JournalMode=WAL',
'StringFormat=Unicode',
'Synchronous=Full',
'UpdateOptions.LockWait=True',
'BusyTimeout=30000',
'SQLiteAdvanced=temp_store=MEMORY;page_size=4096;auto_vacuum=FULL'];
InitiateResource(aParams, aOnNeedCredentials);
end;
procedure TDbInteract.InitiateResource(const aParams: array of string; const aOnNeedCredentials: TOnNeedCredentials);
var
I: Integer;
Credentials: TStringDynArray;
begin
FRowsAffected := 0;
FIsForeignKeyHonored := True;
FOwnsResultDataSets := True;
FDataSetContainer := TDataSetContainer.Create(nil);
FConnection := TFDConnection.Create(nil);
try
for I := Low(aParams) to High(aParams) do
begin
FConnection.Params.Add(aParams[I]);
end;
if Assigned(aOnNeedCredentials) then
begin
aOnNeedCredentials(Self, Credentials);
for I := Low(Credentials) to High(Credentials) do
begin
FConnection.Params.Add(Credentials[I]);
end;
end;
FConnection.Open;
except
raise;
end;
end;
**Identified problems:
- I read somewhere (do not remember the page I was in) that SQLite engine requires full lock on the directory that it wants to write to. and this is the problem. How ever I run the tool as invoker and my account is an admin so that is not a problem. Also I have the same tool written in c# and this problem never occurs.
Solutions I found:
- Run the tool as administrator
- Do not Install the tool in ProgramFiles directory
I really don't like these solutions. and would like to run my tool from program Files directory as it is part of a bigger project.
Note: The database file is in programdata directory. It is created by the tool (this works).
Edit: I just tried putting the DB file in C:\Users\Nacereddine\AppData\Roaming\MyTool
And I still have the same problem when the tool is installed in C:\Program Files (x86)\MyTool
This how I create the DB file
class procedure TDbInteract.CreateSQLiteDb(const aDatabasePath: string; const aTables: TStringDynArray);
var
I: Integer;
aParams: array of string;
aConnection: TFDConnection;
begin
aParams := ['DriverID=SQLite',
'Database=' + aDatabasePath,
'OpenMode=CreateUTF16',
'LockingMode=Normal',
'JournalMode=WAL',
'StringFormat=Unicode',
'Synchronous=Full',
'UpdateOptions.LockWait=True',
'BusyTimeout=30000',
'SQLiteAdvanced=temp_store=MEMORY;page_size=4096;auto_vacuum=FULL'];
aConnection := TFDConnection.Create(nil);
try
for I := Low(aParams) to High(aParams) do
begin
aConnection.Params.Add(aParams[I]);
end;
aConnection.Open();
for I := Low(aTables) to High(aTables) do
begin
aConnection.ExecSQL(aTables[I]);
end;
finally
aConnection.Close;
aConnection.Free;
end;
end;
Note: I do not know if this makes any difference but the Db file is encrypted.