如何检测系统中的 FTDI 驱动程序

How to detect FTDI driver in system

我有一个应用程序需要在系统中安装 FTDI D2XX Direct Drivers 驱动程序。现在我正在使用 Inno Setup 创建安装脚本。如何获取系统 (Windows) 中是否安装了 FTDI 驱动程序的信息。是否有任何路径或注册表项可以检查以获得关于它的明确信息?

发布此答案时我想到了两种方式,但我当时决定展示我的首选方式。为了完整起见,我还提供了一种检查系统中是否存在库的通用方法。

1。尝试调用 FTDI 驱动程序库函数

我认为你能做的最好的事情就是尝试使用延迟加载从驱动程序库本身调用一个函数(delayload option). A good function to call is e.g. the FT_GetLibraryVersion函数,通过它你可以获得库版本,并且不需要打开设备. 下面的示例代码展示了如何测试库是否存在于系统中:

[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;

库函数能不能调用,只是个试探。因此没有结果也没有错误检查。

2。以通用方式检查库的存在

由于 LoadDLLFreeDLL 等函数已弃用(并且没有检查库是否已加载的函数),这是一种检查系统中是否存在库的通用方法需要导入一些 WinAPI 函数。以下函数 LibraryExists 检查给定名称的库是否已被 Inno Setup 加载,如果没有,它会尝试加载和卸载它:

[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;

以及您的案例的可能用法:

function IsFTD2xxInstalled: Boolean;
begin
  Result := LibraryExists('ftd2xx.dll');
end;