mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-04-12 18:30:26 +08:00
HMCLauncher: try bundled JRE
This commit is contained in:
parent
f0c7f54cc6
commit
426ea607e8
Binary file not shown.
Binary file not shown.
@ -23,7 +23,7 @@
|
||||
<ProjectGuid>{672B1019-E741-4C0D-A986-627E2ACE157B}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>HMCL</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>7.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
@ -152,19 +152,25 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="HMCL.h" />
|
||||
<ClInclude Include="java.h" />
|
||||
<ClInclude Include="main.h" />
|
||||
<ClInclude Include="os.h" />
|
||||
<ClInclude Include="Resource.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="Version.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="HMCL.cpp" />
|
||||
<ClCompile Include="java.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="os.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Version.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="HMCL.rc" />
|
||||
|
@ -24,7 +24,16 @@
|
||||
<ClInclude Include="Resource.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HMCL.h">
|
||||
<ClInclude Include="main.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Version.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="java.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="os.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
@ -32,7 +41,16 @@
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HMCL.cpp">
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Version.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="java.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="os.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
15
HMCLauncher/HMCL/Version.cpp
Normal file
15
HMCLauncher/HMCL/Version.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "stdafx.h"
|
||||
#include "Version.h"
|
||||
|
||||
Version::Version(const std::wstring & rawString)
|
||||
{
|
||||
int idx = 0;
|
||||
ver[0] = ver[1] = ver[2] = ver[3] = 0;
|
||||
for (auto &i : rawString)
|
||||
{
|
||||
if (idx >= 4) break;
|
||||
if (i == '.') ++idx;
|
||||
else if (i == '_') ++idx;
|
||||
else if (isdigit(i)) ver[idx] = ver[idx] * 10 + (i - L'0');
|
||||
}
|
||||
}
|
20
HMCLauncher/HMCL/Version.h
Normal file
20
HMCLauncher/HMCL/Version.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class Version
|
||||
{
|
||||
public:
|
||||
int ver[4];
|
||||
|
||||
Version(const std::wstring &rawString);
|
||||
|
||||
bool operator<(const Version &other) const
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (ver[i] != other.ver[i])
|
||||
return ver[i] < other.ver[i];
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
88
HMCLauncher/HMCL/java.cpp
Normal file
88
HMCLauncher/HMCL/java.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include "stdafx.h"
|
||||
#include "java.h"
|
||||
#include "os.h"
|
||||
|
||||
const Version JAVA_8(L"1.8"), JAVA_11(L"11");
|
||||
|
||||
const LPCWSTR JDK_OLD = L"SOFTWARE\\JavaSoft\\Java Development Kit";
|
||||
const LPCWSTR JRE_OLD = L"SOFTWARE\\JavaSoft\\Java Runtime Environment";
|
||||
const LPCWSTR JDK_NEW = L"SOFTWARE\\JavaSoft\\JDK";
|
||||
const LPCWSTR JRE_NEW = L"SOFTWARE\\JavaSoft\\JRE";
|
||||
|
||||
bool oldJavaFound = false, newJavaFound = false;
|
||||
|
||||
bool FindJavaByRegistryKey(HKEY rootKey, LPCWSTR subKey, std::wstring & path)
|
||||
{
|
||||
WCHAR javaVer[MAX_KEY_LENGTH]; // buffer for subkey name, special for JavaVersion
|
||||
DWORD cbName; // size of name string
|
||||
DWORD cSubKeys = 0; // number of subkeys
|
||||
DWORD cbMaxSubKey; // longest subkey size
|
||||
DWORD cValues; // number of values for key
|
||||
DWORD cchMaxValue; // longest value name
|
||||
DWORD cbMaxValueData; // longest value data
|
||||
LSTATUS result;
|
||||
|
||||
HKEY hKey;
|
||||
if (ERROR_SUCCESS != (result = RegOpenKeyEx(rootKey, subKey, 0, KEY_WOW64_64KEY | KEY_READ, &hKey)))
|
||||
return false;
|
||||
|
||||
RegQueryInfoKey(
|
||||
hKey, // key handle
|
||||
NULL, // buffer for class name
|
||||
NULL, // size of class string
|
||||
NULL, // reserved
|
||||
&cSubKeys, // number of subkeys
|
||||
&cbMaxSubKey, // longest subkey size
|
||||
NULL, // longest class string
|
||||
&cValues, // number of values for this key
|
||||
&cchMaxValue, // longest value name
|
||||
&cbMaxValueData, // longest value data
|
||||
NULL, // security descriptor
|
||||
NULL); // last write time
|
||||
|
||||
if (!cSubKeys)
|
||||
return false;
|
||||
|
||||
bool flag = false;
|
||||
for (DWORD i = 0; i < cSubKeys; ++i)
|
||||
{
|
||||
cbName = MAX_KEY_LENGTH;
|
||||
if (ERROR_SUCCESS != (result = RegEnumKeyEx(hKey, i, javaVer, &cbName, NULL, NULL, NULL, NULL)))
|
||||
continue;
|
||||
|
||||
HKEY javaKey;
|
||||
if (ERROR_SUCCESS != RegOpenKeyEx(hKey, javaVer, 0, KEY_READ, &javaKey))
|
||||
continue;
|
||||
|
||||
if (ERROR_SUCCESS == MyRegQueryValue(javaKey, L"JavaHome", REG_SZ, path))
|
||||
{
|
||||
if (Version(javaVer) < JAVA_8)
|
||||
oldJavaFound = true;
|
||||
else if (!(Version(javaVer) < JAVA_11))
|
||||
newJavaFound = true;
|
||||
else
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (flag)
|
||||
break;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool FindJavaInRegistry(std::wstring & path)
|
||||
{
|
||||
return FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JDK_OLD, path) ||
|
||||
FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JRE_OLD, path) ||
|
||||
FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JDK_NEW, path) ||
|
||||
FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JRE_NEW, path);
|
||||
}
|
||||
|
||||
bool FindJava(std::wstring & path)
|
||||
{
|
||||
return FindJavaInRegistry(path) ||
|
||||
ERROR_SUCCESS == MyGetEnvironmentVariable(L"JAVA_HOME", path);
|
||||
}
|
10
HMCLauncher/HMCL/java.h
Normal file
10
HMCLauncher/HMCL/java.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include "Version.h"
|
||||
|
||||
// Find Java installation in system registry
|
||||
bool FindJavaInRegistry(std::wstring &path);
|
||||
|
||||
// Find Java Installation in registry and environment variable
|
||||
bool FindJava(std::wstring &path);
|
79
HMCLauncher/HMCL/main.cpp
Normal file
79
HMCLauncher/HMCL/main.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
#include "stdafx.h"
|
||||
#include "main.h"
|
||||
#include "os.h"
|
||||
#include "java.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
void LaunchJVM(const wstring &javaPath, const wstring &jarPath)
|
||||
{
|
||||
if (MyCreateProcess(L"\"" + javaPath + L"\" -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=15 -jar \"" + jarPath + L"\""))
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
wstring path, exeName;
|
||||
|
||||
// Since Jar file is appended to this executable, we should first get the location of JAR file.
|
||||
if (ERROR_SUCCESS != MyGetModuleFileName(NULL, exeName))
|
||||
return 1;
|
||||
|
||||
|
||||
// First try the Java packaged together.
|
||||
bool is64Bit = false;
|
||||
GetArch(is64Bit); // if failed to determine architecture of operating system, consider 32-bit.
|
||||
|
||||
if (is64Bit)
|
||||
{
|
||||
LaunchJVM(L"jre-x64\\bin\\javaw.exe", exeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
LaunchJVM(L"jre-x86\\bin\\javaw.exe", exeName);
|
||||
}
|
||||
|
||||
if (FindJava(path))
|
||||
LaunchJVM(path + L"\\bin\\javaw.exe", exeName);
|
||||
|
||||
// Try java in PATH
|
||||
LaunchJVM(L"javaw", exeName);
|
||||
|
||||
// Or we try to search Java in C:\Program Files.
|
||||
{
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE hFind = FindFirstFile(L"C:\\Program Files\\Java\\*", &data); // Search all subdirectory
|
||||
|
||||
if (hFind != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
wstring javaw = wstring(L"C:\\Program Files\\Java\\") + data.cFileName + wstring(L"\\bin\\javaw.exe");
|
||||
if (FindFirstFileExists(javaw.c_str(), 0)) {
|
||||
LaunchJVM(javaw, exeName);
|
||||
}
|
||||
} while (FindNextFile(hFind, &data));
|
||||
FindClose(hFind);
|
||||
}
|
||||
}
|
||||
|
||||
// Consider C:\Program Files (x86)\Java
|
||||
{
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE hFind = FindFirstFile(L"C:\\Program Files (x86)\\Java\\*", &data); // Search all subdirectory
|
||||
|
||||
if (hFind != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
wstring javaw = wstring(L"C:\\Program Files (x86)\\Java\\") + data.cFileName + L"\\bin\\javaw.exe";
|
||||
if (FindFirstFileExists(javaw.c_str(), 0)) {
|
||||
LaunchJVM(javaw, exeName);
|
||||
}
|
||||
} while (FindNextFile(hFind, &data));
|
||||
FindClose(hFind);
|
||||
}
|
||||
}
|
||||
|
||||
MessageBox(NULL, L"Java installation cannot be found in this computer, please download it from https://java.com \n"
|
||||
L"未能在这台电脑上找到Java 8~Java 10,请从 https://java.com 下载安装Java", L"Error", MB_ICONERROR | MB_OK);
|
||||
ShellExecute(0, 0, L"https://java.com/", 0, 0, SW_SHOW);
|
||||
return 1;
|
||||
}
|
3
HMCLauncher/HMCL/main.h
Normal file
3
HMCLauncher/HMCL/main.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "resource.h"
|
108
HMCLauncher/HMCL/os.cpp
Normal file
108
HMCLauncher/HMCL/os.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
#include "stdafx.h"
|
||||
#include "os.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
LSTATUS MyRegQueryValue(HKEY hKey, LPCWSTR subKey, DWORD dwType, wstring &out)
|
||||
{
|
||||
DWORD dwSize = 0;
|
||||
LSTATUS ret = RegQueryValueEx(hKey, subKey, 0, &dwType, NULL, &dwSize);
|
||||
if (ret != ERROR_SUCCESS) return ret;
|
||||
WCHAR *buffer = new WCHAR[dwSize];
|
||||
ret = RegQueryValueEx(hKey, subKey, 0, &dwType, (LPBYTE)buffer, &dwSize);
|
||||
if (ret != ERROR_SUCCESS) return ret;
|
||||
out = buffer;
|
||||
delete[] buffer;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LSTATUS MyGetModuleFileName(HMODULE hModule, std::wstring &out)
|
||||
{
|
||||
DWORD res, size = MAX_PATH;
|
||||
out = wstring();
|
||||
out.resize(size);
|
||||
while ((res = GetModuleFileName(hModule, &out[0], size)) == size)
|
||||
{
|
||||
out.resize(size += MAX_PATH);
|
||||
}
|
||||
if (res == 0)
|
||||
return GetLastError();
|
||||
else
|
||||
{
|
||||
out.resize(size - MAX_PATH + res);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
LSTATUS MyGetEnvironmentVariable(LPCWSTR name, std::wstring & out)
|
||||
{
|
||||
DWORD res, size = MAX_PATH;
|
||||
out = wstring();
|
||||
out.resize(size);
|
||||
while ((res = GetEnvironmentVariable(name, &out[0], size)) == size)
|
||||
{
|
||||
out.resize(size += MAX_PATH);
|
||||
}
|
||||
if (res == 0)
|
||||
return GetLastError();
|
||||
else
|
||||
{
|
||||
out.resize(size - MAX_PATH + res);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
bool MyCreateProcess(const std::wstring &command)
|
||||
{
|
||||
wstring writable_command = command;
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
si.cb = sizeof(si);
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
|
||||
return (CreateProcess(NULL, &writable_command[0], NULL, NULL, false, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi));
|
||||
}
|
||||
|
||||
bool FindFirstFileExists(LPCWSTR lpPath, DWORD dwFilter)
|
||||
{
|
||||
WIN32_FIND_DATA fd;
|
||||
HANDLE hFind = FindFirstFile(lpPath, &fd);
|
||||
bool bFilter = (false == dwFilter) ? true : fd.dwFileAttributes & dwFilter;
|
||||
bool ret = ((hFind != INVALID_HANDLE_VALUE) && bFilter) ? true : false;
|
||||
FindClose(hFind);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GetArch(bool & is64Bit)
|
||||
{
|
||||
#if _WIN64
|
||||
isWindows64bit = true;
|
||||
return true;
|
||||
#elif _WIN32
|
||||
typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
|
||||
|
||||
BOOL isWow64 = FALSE;
|
||||
|
||||
// IsWow64Process is not available on all supported versions of Windows.
|
||||
// Use GetModuleHandle to get a handle to the DLL that contains the function
|
||||
// and GetProcAddress to get a pointer to the function if available.
|
||||
|
||||
LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)
|
||||
GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
|
||||
|
||||
if (fnIsWow64Process)
|
||||
{
|
||||
if (!fnIsWow64Process(GetCurrentProcess(), &isWow64))
|
||||
return false;
|
||||
|
||||
is64Bit = isWow64;
|
||||
return true;
|
||||
}
|
||||
else // IsWow64Process is not supported, fail to detect.
|
||||
return false;
|
||||
|
||||
#else
|
||||
#error _WIN64 and _WIN32 are both undefined.
|
||||
#endif
|
||||
}
|
23
HMCLauncher/HMCL/os.h
Normal file
23
HMCLauncher/HMCL/os.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
const int MAX_KEY_LENGTH = 255;
|
||||
const int MAX_VALUE_NAME = 16383;
|
||||
|
||||
// Query registry value of class root hKey, key path subKey, stores result in parameter out.
|
||||
LSTATUS MyRegQueryValue(HKEY hKey, LPCWSTR subKey, DWORD dwType, std::wstring &out);
|
||||
|
||||
// Get module file name, stores result in parameter out.
|
||||
LSTATUS MyGetModuleFileName(HMODULE hModule, std::wstring &out);
|
||||
|
||||
// Get environment variable by name, C++ style, stores the value in parameter out.
|
||||
LSTATUS MyGetEnvironmentVariable(LPCWSTR name, std::wstring &out);
|
||||
|
||||
// Create process by invoking CreateProcess, only pass command.
|
||||
bool MyCreateProcess(const std::wstring &command);
|
||||
|
||||
// Check if file lpPath exists.
|
||||
bool FindFirstFileExists(LPCWSTR lpPath, DWORD dwFilter);
|
||||
|
||||
bool GetArch(bool &is64Bit);
|
Loading…
x
Reference in New Issue
Block a user