如何返回忽略已安装的Java版本的java.exe文件的完整路径?

时间:2018-10-01 22:25:31

标签: delphi delphi-10-seattle

我想使用Windows注册表将我的.jar文件与java.exe关联,并怀疑如何忽略计算机上安装的Java版本返回 java.exe 文件的完整路径。

例如:

就我而言,我有:

  

C:\ Program Files \ Java \ jdk 1.7.0_45 \ bin \ java.exe

那么如何忽略此部分 1.7.0_45 访问java.exe文件?

MaxDeliveryCount

1 个答案:

答案 0 :(得分:0)

不要使用注册表来发现系统文件夹的路径,例如Program Files。请改用SHGetFolderPath()SHGetKnownFolderPath(),例如:

function GetProgramFilesDir: string;
var
  path: array[MAX_PATH] of Char;
begin
  if SHGetFolderPath(0, CSIDL_PROGRAM_FILES, 0, SHGFP_TYPE_CURRENT, path) = S_OK then
    Result := IncludeTrailingPathDelimiter(path)
  else
    Result := '';
end;

function GetProgramFilesDir: string;
var
  path: PChar;
begin
  if SHGetKnownFolderPath(FOLDERID_ProgramFiles, 0, 0, path) = S_OK then
  begin
    try
      Result := IncludeTrailingPathDelimiter(path);
    finally
      CoTaskMemFree(path);
    end;
  end else
    Result := '';
end;

话虽如此,要获取java.exe的当前安装路径,您可以尝试以下几种选择:

  • 检查是否设置了%JAVA_HOME%环境变量。

  • 检查HKLM\SOFTWARE\JavaSoft\Java Runtime Environment\<version>注册表项中的JavaHome值(可能有多个<version>子项!)。

  • %PATH%环境变量中搜索其中包含java.exe的所有列出的文件夹(可能有多个文件夹!)。您可以自己手动解析%PATH%,也可以使用SearchPath(),并将其lpPath参数设置为NULL(如果您只关心找到的java.exe的第一个副本)。

function GetJavaPathViaEnvironment: string;
begin
  Result := GetEnvironmentVariable('JAVA_HOME');
  if Result <> '' then
  begin
    Result := IncludeTrailingPathDelimiter(Result) + 'bin' + PathDelim + 'java.exe';
    // if not FileExists(Result) then Result := '';
  end;  
end;

function GetJavaPathViaRegistry: string;
const
  JAVA_KEY: string = '\SOFTWARE\JavaSoft\Java Runtime Environment\';
  Wow64Flags: array[0..2] of DWORD = (0, KEY_WOW64_32KEY, KEY_WOW64_64KEY);
var
  reg: TRegistry;
  s: string;
  i: integer;
begin
  Result := '';
  reg := TRegistry.Create;
  try
    reg.RootKey := HKEY_LOCAL_MACHINE;
    for i := Low(Wow64Flags) to High(Wow64Flags) do
    begin
      reg.Access := (reg.Access and KEY_WOW64_RES) or Wow64Flags[i];
      if reg.OpenKeyReadOnly(JAVA_KEY) then
      begin
        s := reg.ReadString('CurrentVersion');
        if s <> '' then
        begin
          if reg.OpenKeyReadOnly(s) then
          begin
            s := reg.ReadString('JavaHome');
            if s <> '' then
            begin
              Result := IncludeTrailingPathDelimiter(s) + 'bin' + PathDelim + 'java.exe';
              // if not FileExists(Result) then Result := '' else
              Exit;
            end;
          end;
        end;
        reg.CloseKey;
      end;
    end;
  finally
    reg.Free;
  end;
end;

function GetJavaPathViaSearchPath: string;
var
  path: array[0..MAX_PATH] of Char;
  s: string;
  len: DWORD;
begin
  Result := '';
  len := SearchPath(nil, 'java.exe', nil, Length(path), path, PPChar(nil)^);
  if len <= Length(path) then
    SetString(Result, path, len)
  else
  begin
    repeat
      SetLength(s, len);
      len := SearchPath(nil, 'java.exe', nil, len, PChar(s), PPChar(nil)^);
    until len <= Length(s);
    SetString(Result, PChar(s), len);
  end;
end;

function GetJavaPath: string;
begin
  Result := GetJavaPathViaEnvironment;
  if Result = '' then
    Result := GetJavaPathViaRegistry;
  if Result = '' then
    Result := GetJavaPathViaSearchPath;
end;

此外,请不要忘记带空格的路径必须用双引号引起来。您可以使用Delphi的AnsiQuotedStr()来帮助您,例如:

reg.WriteString('', AnsiQuotedStr(GetJavaPath, '"') + ' "%1"');