【问题标题】:How to determine Windows Java installation location如何确定 Windows Java 安装位置
【发布时间】:2010-06-14 14:39:55
【问题描述】:

我正在尝试从 C# 程序集动态运行 .jar(使用 Process.Start(info))。现在,我可以从控制台应用程序运行:

ProcessStartInfo info = new ProcessStartInfo("java", "-jar somerandom.jar");

然而,在程序集中,我不断收到“系统找不到指定的文件”的Win32Exception,并且必须将行更改为 Java 的完整路径,如下所示:

ProcessStartInfo info = new ProcessStartInfo("C:\\Program Files\\Java\\jre6\\bin\\java.exe", "-jar somerandom.jar");

这显然不行。我需要一种方法来动态(但以声明方式)确定 Java 的安装位置。

我开始考虑查看注册表,但是当我到达那里时,我注意到版本有特定的键并且它们甚至不能保证是数字(例如“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment \1.6" 和 "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.6.0_20")。

从 C# 应用程序中查找最新 java.exe 路径的最可靠的“长期”解决方案是什么?

非常感谢。

- 编辑-

感谢GenericTypeTeaStephen Cleary 的回答,我已经解决了以下问题:

private String GetJavaInstallationPath()
{
    String javaKey = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
    using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(javaKey))
    {
        String currentVersion = baseKey.GetValue("CurrentVersion").ToString();
        using (var homeKey = baseKey.OpenSubKey(currentVersion))
            return homeKey.GetValue("JavaHome").ToString();
    }
}

【问题讨论】:

    标签: c# java windows registry


    【解决方案1】:

    您可以通过注册表进行操作。不过你找错地方了。我为你拼凑了一个简单的例子:

    private string GetJavaInstallationPath()
    {
        string environmentPath = Environment.GetEnvironmentVariable("JAVA_HOME");
        if (!string.IsNullOrEmpty(environmentPath))
        {
           return environmentPath;
        }
    
        string javaKey = "SOFTWARE\\JavaSoft\\Java Runtime Environment\\";
        using (Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(javaKey))
        {
            string currentVersion = rk.GetValue("CurrentVersion").ToString();
            using (Microsoft.Win32.RegistryKey key = rk.OpenSubKey(currentVersion))
            {
                return key.GetValue("JavaHome").ToString();
            }
        }
    }
    

    然后要使用它,只需执行以下操作:

    string installPath = GetJavaInstallationPath();
    string filePath = System.IO.Path.Combine(installPath, "bin\\Java.exe");
    if (System.IO.File.Exists(filePath))
    {
        // We have a winner
    }
    

    【讨论】:

    • 这看起来很完美!感谢您指出我错过了CurrentVersion。不过,我一直在 rk 上收到 NullRef。 ;(
    • 用户可以使用名为“JAVA_HOME”的环境变量覆盖“自动检测到的”java 路径,这是一个常见的约定。程序员应该尊重帽子并给予该变量优先权: string java_path = Environment.GetEnvironmentVariable("JAVA_HOME") ?? GetJavaInstallationPath();
    • @Lance - 我不是 java 专家,所以这只是一个最佳猜测。你有没有看一下钥匙是否在那里? @SchlaWiener - 更新了我的答案以反映您的评论(我认为)。
    • @GenericTypeTea:是的,它就在那里。我的问题中列出的密钥存在(通过 RegEdit 获得)。 @SchlaWiener:非常感谢。那是我以后不必被踢的事情。 ;)
    • @Lance - 如果钥匙在那里,我不知道为什么它会返回 null 。恐怕要由你来调试它。如果您发现原因,请报告。
    【解决方案2】:

    只是一个快速的碰撞,因为我找到了比所有者选择的答案更好的解决方案。

    我发现它仅适用于 32 位 Java,而今天已经过时了。为此我对64位系统进行了调整。希望这可以帮助其他正在寻找方法的人。

            private string GetJavaInstallationPath()
            {
                string environmentPath = Environment.GetEnvironmentVariable("JAVA_HOME");
                if (!string.IsNullOrEmpty(environmentPath))
                {
                    return environmentPath;
                }
                string javaKey = "SOFTWARE\\JavaSoft\\Java Runtime Environment\\";
                if (!Environment.Is64BitOperatingSystem)
                {
                    using (Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(javaKey))
                    {
                        string currentVersion = rk.GetValue("CurrentVersion").ToString();
                        using (Microsoft.Win32.RegistryKey key = rk.OpenSubKey(currentVersion))
                        {
                            return key.GetValue("JavaHome").ToString();
                        }
                    }
                }
                else
                {
                    using (var view64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
                                                                RegistryView.Registry64))
                    {
                        using (var clsid64 = view64.OpenSubKey(javaKey))
                        {
                            string currentVersion = clsid64.GetValue("CurrentVersion").ToString();
                            using (RegistryKey key = clsid64.OpenSubKey(currentVersion))
                            {
                                return key.GetValue("JavaHome").ToString();
                            }
                        }
                    }
                }
    
            }
    

    【讨论】:

      【解决方案3】:

      据我所知,系统上安装的最新版本的 Java 是在 PATH 环境变量中找到的第一个版本,因此您无需查找任何注册表项,只需运行即可。

      试试:

      ProcessStartInfo info = new ProcessStartInfo("java.exe", "-jar somerandom.jar");
      

      如果它不起作用,请确保 java.exe 在您的路径中并告诉我。

      【讨论】:

      • 不幸的是,没有。如果我检查info.EnvironmentVariables["path"],它不包含Java。另一方面,如果我只是打开一个命令提示符,我可以整天> java -jar somerandom.jar,所以我知道它应该在那里。
      • 当你从命令提示符运行它时,你能检查它运行的是哪个 java.exe 进程吗?
      • @LanceMay,你也试过在进程名称后面加扩展名的版本吗?
      • 是的,它们在两种情况下都可以工作和不工作。两者似乎没有区别。
      【解决方案4】:

      建立在@GenericTypeTea 问题之上 - 这是一种在 x32/x64 上同时检查的方法。

      static string GetJavaInstallationPath()
      {
        string environmentPath = Environment.GetEnvironmentVariable("JAVA_HOME");
        if (!string.IsNullOrEmpty(environmentPath))
        {
          return environmentPath;
        }
      
        const string JAVA_KEY = "SOFTWARE\\JavaSoft\\Java Runtime Environment\\";
      
        var localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32);
        using (var rk = localKey.OpenSubKey(JAVA_KEY))
        {
          if (rk != null)
          {
            string currentVersion = rk.GetValue("CurrentVersion").ToString();
            using (var key = rk.OpenSubKey(currentVersion))
            {
              return key.GetValue("JavaHome").ToString();
            }
          }
        }
      
        localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
        using (var rk = localKey.OpenSubKey(JAVA_KEY))
        {
          if (rk != null)
          {
            string currentVersion = rk.GetValue("CurrentVersion").ToString();
            using (var key = rk.OpenSubKey(currentVersion))
            {
              return key.GetValue("JavaHome").ToString();
            }
          }
        }
      
        return null;
      }
      

      【讨论】:

      • msdn.microsoft.com/en-us/library/dd411615(v=vs.110).aspx 在 64 位版本的 Windows 上,注册表的各个部分分别存储用于 32 位和 64 位应用程序。 32 位应用程序有 32 位视图,64 位应用程序有 64 位视图。如果视图是 Registry64 但远程机器运行的是 32 位操作系统,则返回的键将使用 Registry32 视图。
      • 因此只需调用从 Registry64 视图打开密钥就足以涵盖 32/64 位操作系统的情况。
      【解决方案5】:

      首先,不要试图从环境变量中获取 java JDK,使用注册表键更有效,并且会给你任何需要的东西。这是一个检查它是否存在的示例,如果它确实存在,它可以返回当前版本的相对路径或名称。我花了几个小时来完成这项工作,我希望它对某人有所帮助。如果它有助于 32 位 JDK 将被停止,所以我只提供了 64 位解决方案。

      public static string checkInstalled(string findByName)
          {
              string displayName;
              string InstallPath;
              string registryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
      
              //64 bits computer
              RegistryKey key64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
              RegistryKey key = key64.OpenSubKey(registryKey);
      
              if (key != null)
              {
                  foreach (RegistryKey subkey in key.GetSubKeyNames().Select(keyName => key.OpenSubKey(keyName)))
                  {
                      displayName = subkey.GetValue("DisplayName") as string;
                      if (displayName != null && displayName.Contains(findByName))
                      {
      
                          InstallPath = subkey.GetValue("InstallLocation").ToString();
      
                          return InstallPath; //or displayName
      
                      }
                  }
                  key.Close();
              }
      
              return null;
          }
      

      你可以这样调用这个方法

      string JavaPath = Software.checkInstalled("Java(TM) SE Development Kit");
      

      和繁荣。干杯

      【讨论】:

        猜你喜欢
        • 2020-10-18
        • 2022-12-31
        • 2013-02-23
        • 1970-01-01
        • 2021-12-27
        • 2013-08-10
        • 2018-07-14
        • 1970-01-01
        • 2018-09-21
        相关资源
        最近更新 更多