最近用JAVA的SWING框架写了一个小工具,但由于JAVA在使用前想检查一下用户是否安装了JAVA虚拟机。
于是用MFC来完成检测的工作,然后调用JAVA.exe来启动工具。
在网上找了一些方案,感觉比较靠谱的是从注册表中的获取JAVA安装路径,然后检查这个路径是否存在。
(这年头GOOGLE被墙,程序也只会百度了,如果百度没了,怎么办?)
其间碰到两个比较蛋疼的事情:
1、在32位系统上运行正常,在64位上使用RegOpenKeyEx()出错。他会返回一个错误码,现在记不清了。
查了一下原来第4个参数REGSAM出了问题。
REGSAM regsam = KEY_QUERY_VALUE ;
这样能在32位系统上运行。
REGSAM regsam = KEY_QUERY_VALUE | KEY_WOW64_64KEY;
这样才能在64位系统上运行。
后来问题就这样解决了,虽知其然,但不知其所以然,比较悲惧,下次碰到估计又要跪。
2、一直以为jvm.dll就是放在%java_home%/bin/client/目录中,尼马,装完JDK1.8, JDK1.7, JDK1.6后神奇的发现%java_home%/bin/server/中也会有jvm.dll存在,具体看你的JAVA或JRE版本,那么多版本,不知道用户会装哪个版本啊。没法,只能找完%java_home%/bin/clinet/目录,再找%java_home%/bin/server/目录。找到了就算有JAVA环境吧。方法比较笨,问题算解决了。不知道有没有高人指点,有更科学的办法。后找了一下,发现JAVA虚拟机的创建会分很多版本,还有一个文件(jvm.cfg)控制。具体创建哪个JAVA虚拟机就看这个文件了。再深入的研究就没有尝试了。
最后贴上相关代码,方便大家一起交流:
#include "stdafx.h" #include "JavaEnv.h" #include "Log.h" #include <Windows.h> // 安全的取得真实系统信息 VOID SafeGetNativeSystemInfo(__out LPSYSTEM_INFO lpSystemInfo) { if (NULL == lpSystemInfo) return; typedef VOID(WINAPI *LPFN_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo); LPFN_GetNativeSystemInfo fnGetNativeSystemInfo = (LPFN_GetNativeSystemInfo)GetProcAddress(GetModuleHandle("kernel32"), "GetNativeSystemInfo");; if (NULL != fnGetNativeSystemInfo) { fnGetNativeSystemInfo(lpSystemInfo); } else { GetSystemInfo(lpSystemInfo); } } // 获取操作系统位数 int GetSystemBits() { SYSTEM_INFO si; SafeGetNativeSystemInfo(&si); if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) { return 64; } return 32; } char* GetJreHome(int BIT, REGSAM regsam) { #define MYBUFF 123 HKEY hKey; long lRet; CHAR* dir = new CHAR[MYBUFF]; DWORD dwBufLen = MYBUFF; CHAR* s = new CHAR[MYBUFF]; if (BIT == 64) { strncpy_s(s, MYBUFF, "SOFTWARE\\Wow6432Node\\JavaSoft\\Java Runtime Environment\\", MYBUFF); } else { strncpy_s(s, MYBUFF, "SOFTWARE\\JavaSoft\\Java Runtime Environment\\", MYBUFF); } lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, s, 0, regsam, &hKey); if (lRet != ERROR_SUCCESS) return NULL; lRet = RegQueryValueEx(hKey, "CurrentVersion", NULL, NULL, (LPBYTE)dir, &dwBufLen); RegCloseKey(hKey); if (lRet != ERROR_SUCCESS) return NULL; strcat_s(s, MYBUFF, dir); lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, s, 0, regsam, &hKey); if (lRet != ERROR_SUCCESS) return NULL; dwBufLen = MYBUFF; lRet = RegQueryValueEx(hKey, "JavaHome", NULL, NULL, (LPBYTE)dir, &dwBufLen); RegCloseKey(hKey); delete s; if (lRet != ERROR_SUCCESS) return NULL; return dir; } const char* JavaEnv::getJvmPath() { const static int PATH_LEN = 512; static char PATH_JVM[PATH_LEN] = { 0 }; if (PATH_JVM[0] != 0) { return PATH_JVM; } #ifdef NDEBUG ILog log; #else Log log; #endif // NDEBUG ILog* pLog = &log; int bit = GetSystemBits(); REGSAM regsam = KEY_QUERY_VALUE; if (bit == 64) { regsam |= KEY_WOW64_64KEY; } const char* path = GetJreHome(32, regsam); if (path == NULL) { path = GetJreHome(64, regsam); if (path == NULL) { return PATH_JVM; } } const static const char* DIR_JVM[2]; DIR_JVM[0] = "bin\\client\\jvm.dll"; DIR_JVM[1] = "bin\\server\\jvm.dll"; for (int i = 0; i < 2; i++) { int len = strlen(path); char ch = path[len - 1]; if (ch == '\\' || ch == '/') { sprintf_s(PATH_JVM, "%s%s", path, DIR_JVM[i]); } else { sprintf_s(PATH_JVM, "%s\\%s", path, DIR_JVM[i]); } fstream file; file.open(PATH_JVM, ios::in); if (!file) { PATH_JVM[0] = 0; } else { file.close(); break; } } return PATH_JVM; }