I have an app that requires FTDI D2XX Direct Drivers drivers to be installed in system. Now I am creating an installation script using Inno Setup. How can I get an information whether FTDI drivers are installed in system (Windows). Is there any path or registry entry that could be checked to gain unambiguous information about that?
There were two ways I was thinking of when posting this answer, but I've decided to show my preferred one that time. For the sake of completeness, I'm including also a generic way to check whether a library is present in the system.
I think the best you can do is trying to call a function from the driver's library itself using delayed loading (delayload
option). A good function to call is e.g. the FT_GetLibraryVersion
function, by which you can get the library version, and which does not require opened device. In the following example code is shown just how to test whether the library is present in the system:
[Code]
type
ULONG = Cardinal;
FT_STATUS = ULONG;
function FT_GetLibraryVersion(out lpdwVersion: DWORD): FT_STATUS;
external '[email protected] stdcall delayload';
function IsFTD2xxInstalled: Boolean;
var
Version: DWORD;
begin
Result := True;
try
FT_GetLibraryVersion(Version);
except
Result := False;
end;
end;
It's just a probe if a library function can be called. Hence there is no result nor error checking.
Since the functions like LoadDLL
and FreeDLL
are deprecated (and there's no function to check if the library is already loaded), a generic way for checking whether a library is present in the system requires importing a few WinAPI functions. The following function LibraryExists
checks whether a library of a given name is already loaded by Inno Setup and if not, it tries to load and unload it:
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
const
ERROR_MOD_NOT_FOUND = 126;
type
HINSTANCE = THandle;
HMODULE = HINSTANCE;
function LoadLibrary(lpLibFileName: string): HMODULE;
external 'LoadLibrary{#AW}@kernel32.dll stdcall';
function FreeLibrary(hLibModule: HMODULE): BOOL;
external '[email protected] stdcall';
function GetModuleHandle(lpModuleName: string): HMODULE;
external 'GetModuleHandle{#AW}@kernel32.dll stdcall';
procedure RaiseLastError(const Message: string; const Exclude: array of LongInt);
var
I: Integer;
LastError: LongInt;
begin
LastError := DLLGetLastError;
for I := 0 to GetArrayLength(Exclude) - 1 do
if Exclude[I] = LastError then
Exit;
RaiseException(Format('%s' + #13#10 + '%d: %s', [Message, LastError,
SysErrorMessage(LastError)]));
end;
function IsModuleLoaded(const Name: string): Boolean;
begin
Result := GetModuleHandle(Name) <> 0;
if not Result then
RaiseLastError('GetModuleHandle call failed.', [ERROR_MOD_NOT_FOUND]);
end;
function LibraryExists(const Name: string): Boolean;
var
Handle: HMODULE;
begin
Result := IsModuleLoaded(Name);
if not Result then
begin
Handle := LoadLibrary(Name);
if Handle <> 0 then
begin
Result := True;
FreeLibrary(Handle);
end
else
RaiseLastError('LoadLibrary call failed.', [ERROR_MOD_NOT_FOUND]);
end;
end;
And a possible usage for your case:
function IsFTD2xxInstalled: Boolean;
begin
Result := LibraryExists('ftd2xx.dll');
end;