[Solved] - Search for a file lazarus / 62-General ---------------------------------------------------------------------- Rayvenhaus · 2017-03-21 13:37 Good morning everyone. I've run into a bit of a issue with the following code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if FileExists('./sqlite3.dll') then    begin      frm_wyckersetup.uELED1.Color:=clLime;    end  else    begin      frm_wyckersetup.uEled1.Color:=clLime;      SearchCount:=0;      if FindFirst('sqlite3.dll', faAnyFile and faDirectory, SearchInfo)=0 then        begin          Repeat            Inc(SearchCount);          With SearchInfo do              begin                If (Attr and faDirectory) = faDirectory then                  //Test              end;          until FindNext(SearchInfo)<>0;        end;        FindCLose(SearchInfo);        if SearchCount = 0 then          begin          Logger.Error('Missing sqlite3.dll.');            frm_wyckersetup.uEled1.Color:=clRed;            if MessageDlg('Missing Required File', 'Wycker can not start. SQL Library file (sqlite3.dll) is missing. Please locate this file and place it in the same directory that you installed Wycker in.', mtConfirmation, [mbYes],0) = mrYes then              begin                Application.Terminate;            end;          end;    end; What I'm trying to do is search the hard drive to see if the sqlite3.dll is available.  It should be available in the directory that ,y p[ropgram resides in and this snippet of code appears to work correctly if it's there or not, but this snippet does not appear to find the DLL if it resides anywhere else on the HD. Am I doing something wrong? ---------------------------------------------------------------------- jacmoe · 2017-03-21 13:56 Why not skip all of that and try to use a SQLite function? If it fails, then the SQLite DLL can't be found/loaded. ---------------------------------------------------------------------- sky_khan · 2017-03-21 14:06 Which components do you use for sqlite ? AFAIK, standart SqlDB components requires sqlite3.dll present before your application loaded anyway. You have to load dll manually after your program loaded and use getProcAddress for each exported function of it for this to work otherwise OS wont load your program and gives missing library error before your search code get executed. ---------------------------------------------------------------------- jacmoe · 2017-03-21 14:28 By the looks of it, he is writing a setup program, SkyKhan. ---------------------------------------------------------------------- sky_khan · 2017-03-21 14:52 Well, Ok. In that case, Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Button1Click(Sender: TObject);var  FileList: TStrings;begin  FileList:=FindAllFiles('C:\','sqlite3.dll');  Memo1.Lines.Assign(FileList);  FileList.Free;end;  It will take some time if you search all disk, you must be patient. ---------------------------------------------------------------------- Rayvenhaus · 2017-03-21 14:53 Well, basically, I am adding database functions into my program, Wycker.  This is the first time I've ever worked with databases in Pascal and it's a learning curve. What I am trying to do it, on startup of the program, look to see if required files are present. If sqlite3.dll is missing, I want the program to exit.  If the database is missing, I'm going add code to create it. If the DLL is missing, I want to notify the user to install it, although my installation program will place it in the program directory when the program is installed. The problem I'm seeing with the snippet above is that, if the required DLL is not in the program directory, it correctly identifies that and exists. But, what is they already have the DLL in the, for example, c:\windows\system32 directory?  If it's there, the program should be able to run. ---------------------------------------------------------------------- sky_khan · 2017-03-21 15:08 @Rayvenhaus, This is even more easy FindDefaultExecutablePath('sqlite3.dll'); finds which dll would be loaded by searching system path or returns empty string if there is none. ---------------------------------------------------------------------- Rayvenhaus · 2017-03-21 15:24 I can not find a reference to 'FindDefaultExecutablePath' anywhere.  Can you point me to where this is documented? ---------------------------------------------------------------------- sky_khan · 2017-03-21 15:47 Well, IDK about documentation. I prefer reading code if I have a chance. Try this on new project, Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Button1Click(Sender: TObject);begin  ShowMessage(FindDefaultExecutablePath('sqlite3.dll'));end;  it will show you first match of sqlite3.dll in your system path. Now return to Lazarus, hold your CTRL key and click on "FindDefaultExecutablePath" in source editor. It will go to where it is defined. Then hold CTRL+Shift and press down arrow. It will go to where it is implemented. It is in FileUtil unit which is included in uses clause of your main form for default project. You can see what exactly this function is doing there. ---------------------------------------------------------------------- Rayvenhaus · 2017-03-21 17:22 So, if I read that right, it will return a NULL if it does not find the file in the programs directory OR in the system paths.  Correct? ---------------------------------------------------------------------- sky_khan · 2017-03-21 17:45 On windows, yes. I thought that was what you wanted ? ---------------------------------------------------------------------- Rayvenhaus · 2017-03-21 18:23 Yep, windows, however, does this snippet you provided only search the system paths? ---------------------------------------------------------------------- sky_khan · 2017-03-21 18:45 Loading dynamic libraries from application's path is a windows thing. Normally on unix or linux,  executables or libraries is searched only on system path. It does not execute a program or load a library just because it is in your current path. They must be on system path. Thats why i said "on windows". Whatever, FindDefaultExecutablePath is exactly what you asked in your first post.  It looks for your application path first and keeps looking every directory in your system path until it finds one or it returns an empty string. If you give Windows an absolute path to execute a program or load a dll it wont search  it just looks where you said otherwise if you give it only a filename, that is how Windows decides which exe or dll will be loaded. FindDefaultExecutablePath is imitation of how Windows search for exe or dlls. If I still could not explain it with my limited English sorry, I dont know how Again, FindDefaultExecutablePath is your answer. ---------------------------------------------------------------------- Rayvenhaus · 2017-03-21 20:49 That makes perfect sense.  And, yes it will help very much as it cuts way back on the lines of code needed. Here's what I have come up with to search the programs directory and the system paths: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if FileExists('./sqlite3.dll') then    begin      frm_wyckersetup.uELED1.Color:=clLime;      Logger.Info('SQLite DLL found in program directory.');      //Activate Datebase Connection    SQLDBLibraryLoader1.ConnectionType:='SQLite3';      SQLDBLibraryLoader1.LibraryName := '.\sqlite3.dll';      SQLDBLibraryLoader1.Enabled := true;      SQLDBLibraryLoader1.LoadLibrary;    end  else    begin      searchResult := FindDefaultExecutablePath('sqlite3.dll');      if searchResult = '' then        begin          Logger.Error('Missing sqlite3.dll.');          frm_wyckersetup.uEled1.Color:=clRed;        if MessageDlg('Missing Required File', 'Wycker can not start. SQL Library file (sqlite3.dll) is missing. Please locate this file and place it in the same directory that you installed Wycker in.', mtConfirmation, [mbYes],0) = mrYes then            begin              Application.Terminate;            end        end      else        begin          Logger.Info('SQLite DLL library found in system path.');          frm_wyckersetup.uEled1.Color:=clLime;          //Activate Datebase Connection          SQLDBLibraryLoader1.ConnectionType:='SQLite3';          SQLDBLibraryLoader1.LibraryName := '.\sqlite3.dll';          SQLDBLibraryLoader1.Enabled := true;          SQLDBLibraryLoader1.LoadLibrary;        end    end; ---------------------------------------------------------------------- Kays · 2017-03-21 21:28 Quote from: jacmoe on March 21, 2017, 02:56:49 pmWhy not skip all of that and try to use a SQLite function? If it fails, then the SQLite DLL can't be found/loaded. Bad. I hate programs not providing some meaningful error messages.Quote from: Rayvenhaus on March 21, 2017, 03:53:36 pm[…]If sqlite3.dll is missing, I want the program to exit.[…]Good, that way you can either print “could not start, because DB not found” or say that the DB library you're using failed. PS: Worst error message ever: “ERROR: unknown error” ---------------------------------------------------------------------- jacmoe · 2017-03-21 21:36 Quote from: Kays on March 21, 2017, 10:28:23 pmQuote from: jacmoe on March 21, 2017, 02:56:49 pmWhy not skip all of that and try to use a SQLite function? If it fails, then the SQLite DLL can't be found/loaded. Bad. I hate programs not providing some meaningful error messages.I, on the other hand, hate when people are jumping to conclusions... Obviously, if the operation fails due to a missing DLL, the program should handle the error and continue to produce a nice error message. That approach doesn't care where the DLL is, as long as it's available to be used. And if it isn't available, it should behave properly and report the error to the user. ---------------------------------------------------------------------- Rayvenhaus · 2017-03-21 22:28 Which is what the second code snippet does perfectly now. Thanks to everyone for the help.