4

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?

DamurDamuros
  • 63
  • 1
  • 5

1 Answers1

4

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.

1. Try to call an FTDI driver library function

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 'FT_GetLibraryVersion@ftd2xx.dll 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.

2. Check the library presence in a generic way

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 'FreeLibrary@kernel32.dll 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;
TLama
  • 75,147
  • 17
  • 214
  • 392
  • Maybe the first check should be whether the .dll library is present in system. – Slappy Jan 09 '15 at 08:34
  • @Slappy, I was thinking of this. But I've decided to use this way since this verifies that a library named ftd2xx.dll is really a FTDI driver lib (or at least fakes it). And it shows that you can get a version of it which might be handy for someone. Finally, the `LoadDLL` function is deprecated hence this check would officially require importing WinAPI function (such as `LoadLibraryEx`). – TLama Jan 09 '15 at 08:49
  • @Slappy, for the sake of completness I've posted also the generic way. – TLama Jan 09 '15 at 10:52