2005. április 13., szerda

Determine the default browser


Problem/Question/Abstract:

This article describes how to determine the default browser and its version

Answer:

The WinAPI provides an excellent function for this purpose: FindExecutable. This function returns the application associated with the given file. The application associated with a .htm file is the default browser.
The prototype is

function FindExecutable(FileName, Directory: PChar; Result: PChar): HINST;

Unfortunately this function needs an existent file. For this reason it is necessary to create a temporary one.

Basic function

The basic function performs the following steps:

Determine the temp directory
Create a file with ".htm" extension.
Use FindExecutable
Delete the temporary file

type
  TBrowserInformation = record
    Name: string;
    Path: string;
    Version: string;
  end;

function GetDefaultBrowser: TBrowserInformation;
var
  tmp: PChar;
  res: PChar;

begin
  tmp := StrAlloc(255);
  res := StrAlloc(255);

  try
    GetTempPath(255, tmp);
    FileCreate(tmp + 'htmpl.htm');
    FindExecutable('htmpl.htm', tmp, Res);
    Result.Name := ExtractFileName(res);
    Result.Path := ExtractFilePath(res);
    SysUtils.DeleteFile(tmp + 'htmpl.htm');
  finally
    StrDispose(tmp);
    StrDispose(res);
  end;
end;


Long File Name

Now, if you run that function you will notice that there is a small inconvenience: The function returns the location of the default browser as short path. The next function will try to convert it to the long format.

function LongPathName(ShortPathName: string): string;
var
  PIDL: PItemIDList;
  Desktop: IShellFolder;
  WidePathName: WideString;
  AnsiPathName: AnsiString;
begin
  Result := ShortPathName;
  if Succeeded(SHGetDesktopFolder(Desktop)) then
  begin
    WidePathName := ShortPathName;
    if Succeeded(Desktop.ParseDisplayName(0, nil, PWideChar(WidePathName), ULONG(nil^), PIDL, ULONG(nil^))) then
    try
      SetLength(AnsiPathName, MAX_PATH);
      SHGetPathFromIDList(PIDL, PChar(AnsiPathName));
      Result := PChar(AnsiPathName);
    finally CoTaskMemFree(PIDL);
    end;
  end;
end;

Version Information

The next step is to extend the basic function with error handling and the ability to get the default browsers version.

function GetDefaultBrowser: TBrowserInformation;
var
  tmp: PChar;
  res: PChar;
  Version: Pointer;
  VersionInformation: Pointer;
  VersionInformationSize: Integer;
  Dummy: Integer;

begin
  tmp := StrAlloc(255);
  res := StrAlloc(255);

  Version := nil;

  try
    GetTempPath(255, tmp);

    if FileCreate(tmp + 'htmpl.htm') <> -1 then
    begin
      if FindExecutable('htmpl.htm', tmp, res) > 32 then
      begin
        Result.Name := ExtractFileName(res);
        Result.Path := LongPathName(ExtractFilePath(res));

        // Try to determine the Browser Version

        VersionInformationSize := GetFileVersionInfoSize(Res, Dummy);

        if VersionInformationSize > 0 then
        begin
          GetMem(VersionInformation, VersionInformationSize);
          GetFileVersionInfo(Res, 0, VersionInformationSize, VersionInformation);

          VerQueryValue(VersionInformation, ('StringFileInfo040904E4ProductVersion'),
            Pointer(Version), Dummy);

          if Version <> nil then
            Result.Version := PChar(Version);

          FreeMem(VersionInformation);
        end;
      end
      else
        raise EGetDefaultBrowser.Create('Can''t determine the executable.');

      SysUtils.DeleteFile(tmp + 'htmpl.htm');
    end
    else
      raise EGetDefaultBrowser.Create('Can''t create temporary file.');

  finally
    StrDispose(tmp);
    StrDispose(res);
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése