return如何忽略java版本安装的java.exe文件的完整路径?

How return the complete path of java.exe file ignoring java version installed?

我想关联我的 .jar 文件以使用 Windows 注册表以 java.exe 打开,并且对如何 return [=27] 的完整路径有疑问=] 文件忽略计算机上安装的 java 版本。

例如:

就我而言,我有:

C:\Program Files\Java\jdk1.7.0_45\bin\java.exe

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

uses
  Windows, Registry;

function GetProgramFilesDir: string;
  var
    reg: TRegistry;
  begin
    reg := TRegistry.Create;
    try
      reg.RootKey := HKEY_LOCAL_MACHINE;
      reg.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion', False);
      Result := reg.ReadString('ProgramFilesDir');
    finally
      reg.Free;
    end;
  end;

procedure RegisterFileType(cMyExt, cMyFileType, ExeName: string);
var
  reg: TRegistry;
begin
  reg := TRegistry.Create;
  try
    reg.RootKey := HKEY_CURRENT_USER;
    if reg.OpenKey('\Software\Classes\.jar', True) then
      reg.WriteString('', 'MyAppDataFile');
    if reg.OpenKey('\Software\Classes\MyAppDataFile', True) then
      reg.WriteString('', 'myappname'); 
    if reg.OpenKey('\Software\Classes\MyAppDataFile\DefaultIcon', True) then
      reg.WriteString('', GetProgramFilesDir + '\Java\jdk1.7.0_45\bin\java.exe');
    if reg.OpenKey('\Software\Classes\MyAppDataFile\shell\open\command', True)
    then
      reg.WriteString('', GetProgramFilesDir + '\Java\jdk1.7.0_45\bin\java.exe "%1"');
  finally
    reg.Free;
  end;
  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
end;

不要使用注册表来发现系统文件夹的路径,如 Program Files。使用 SHGetFolderPath() or 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"');