自写Windows下的Java多版本管理

原文地址:Windows下的Java多版本管理 | ZYG's Notes (creeeeeeeeeeper.github.io)

使用说明

注意:此版本管理器用来设置全局Java版本,暂无局部修改功能(以后可能会加吧……)

下载

点击此处可以下载jvm.exe,放到一个不碍事的地方(藏起来也可以!)

配置系统变量

首先确保系统变量和用户变量中没有配乱的Java环境变量,建议全部删除掉

全部删掉后,在系统变量中新建一个CLASSPATH变量,值为%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\bin在系统变量的Path变量中新建一个%CLASSPATH%

系统变量的配置就完了。

jvm.exe

初始化

写完JavaVersionManager发现首字母缩写和JavaVirtualMachine一样,不过没关系,用起来感觉也差不多,所以就还是叫jvm吧。

首先使用cmd运行jvm.exe,第一次会出现如下初始化信息:

如果这样就是初始化完成了,初始化时会在C:\User\<your username>这个路径下面产生一个配置文件,JavaVersionManager.ini,不要更改这个文件的内容。被管理的版本会存在这里,如果创建失败可以手动创建

配置版本管理器的环境变量

给jvm.exe配置环境变量

首先将jvm.exe放到一个不碍事的地方,然后配置jvm.exe的环境变量,这样在所有地方就可以用jvm的指令直接运行版本管理器(如下图)。

设置方法

cmd中运行jvm.exe,使用jvm.exe -set-ev指令自动配置环境变量,配置后后不要更改jvm.exe的程序名。由于配置的是系统环境变量,所以需要确认UAC。

配置好后会出现Environment variable has been set successfully.

指令说明

-set-ev

上面介绍过,用来设置JavaVersionManager自己的环境变量

-version

查看JavaVersionManager的版本

-versions

相当于java -version,查看当前的Java版本

-list

列举被添加到管理器中的jdk版本

-add <path> <describe version>

向管理器中添加jdk版本。黄色的警告一般来说不用管,用管理员身份启动可能就没这个问题

如:add D:\Programming\Java\jkd21 21

-set describe version>

如:-set 21

这样后会弹出UAC提示,确认后%JAVA_HOME%会改成jdk21的路径,重新启动一个终端,使用java -version查看是否改好了版本

-remove <describe version>

如:使用-remove 21,可以删除管理器中的版本,不会删除你下载的jdk文件夹,只是不再对其进行管理!!

以后加个直接能下载的功能。。。嗯,以后再说

源码:C语言写的,写着玩的,代码有很多不足之处,轻喷哈哈哈

JavaVersionManager.h

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <io.h> 
#include <errno.h> 
#include <string.h>
#include <ctype.h>
#include <windows.h>
#include <direct.h>

 JavaVersionManager.cpp

#include "JavaVersionManager.h"

char up[0x200];
int IfRunAsAdmin = 0;

int getUserProfile()
{
	const char* userProfile;
	size_t size;

	if (_dupenv_s((char**)&userProfile, &size, "USERPROFILE") != 0 || userProfile == NULL) {
		printf("\033[41mJavaVersionManager\033[0m\033[1m: Initialize failed.  Excpetion: cannot get user profile path.\n");
		return 1;
	}
	strncpy_s(up, sizeof(up), userProfile, _TRUNCATE);
	free((void*)userProfile);
	return 0;
}

int InitConfigFile()
{
	char filePath[0x400];
	snprintf(filePath, sizeof(filePath), "%s\\JavaVersionManager.ini", up);

	FILE* file;
	errno_t err = fopen_s(&file, filePath, "w");
	if (err != 0) {
		perror("\033[41mJavaVersionManager\033[0m\033[1m: Failed to open file for writing.");
		return 1;
	}
	fprintf(file, "# JavaVersionManager Configuration File\n");
	fclose(file);
	printf("\033[42mJavaVersionManager\033[0m\033[1m: Initialized successfully.\n");
	return 0;
}

void prthp()
{
	printf("\n");
	printf("\tUsage: -set-ev\n");
	printf("\t       -version\n");
	printf("\t       -versions\n");
	printf("\t       -list\n");
	printf("\t       -add <path> <descibe version>\n");
	printf("\t       -set <descibe version>\n");
	printf("\t       -remove <descibe version>\n");
	printf("\t       -help\n\n");
	printf("\tuse \"-set-ev\" to set environment variable for JavaVersionManager that you can run as \"jvm\"\n");
	printf("\t\"path\" refers to the path of the JDK directory\n");
	printf("\t\"describe version\"similar to naming your JDK, when change version you can use, only accept Integer\n\n");
}

int isPureDigit(const char* str) {
	while (*str) {
		if (*str < '0' || *str > '9') {
			return 0;
		}
		str++;
	}
	return 1;
}

void CreateAdminProcess(const char* jdkpath) {
	char command[512];
	snprintf(command, sizeof(command), "setx /M JAVA_HOME \"%s\"", jdkpath);
	char fullCommand[600];
	snprintf(fullCommand, sizeof(fullCommand), "cmd.exe /C %s", command);
	STARTUPINFOA si;
	PROCESS_INFORMATION pi;
	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	ZeroMemory(&pi, sizeof(pi));
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;
	HINSTANCE result = ShellExecuteA(
		NULL,
		"runas",
		"cmd.exe",
		fullCommand,
		NULL,
		SW_HIDE
	);
	if ((intptr_t)result <= 32) {
		IfRunAsAdmin = 0;
	}
	else {
		IfRunAsAdmin = 1;
	}
}

DWORD WINAPI ThreadFunction(LPVOID lpParam) {
	const char* jdkpath = (const char*)lpParam;
	CreateAdminProcess(jdkpath);
	return 0;
}

void remove_empty_lines() {
	FILE* file;
	errno_t err = fopen_s(&file, up, "r");
	if (err != 0 || file == NULL) {
		perror("\033[43mJavaVersionManager\033[0m\033[1m: Something wrong happened, but they are not important...");
		return;
	}
	FILE* temp_file;
	err = fopen_s(&temp_file, "temp.ini", "w");
	if (err != 0 || temp_file == NULL) {
		perror("\033[43mJavaVersionManager\033[0m\033[1m: Something wrong happened, but they are not important...");
		fclose(file);
		return;
	}
	char line[256];
	while (fgets(line, sizeof(line), file)) {
		if (strcmp(line, "\n") != 0) {
			fputs(line, temp_file);
		}
	}
	fclose(file);
	fclose(temp_file);

	if (remove(up) != 0) {
		perror("\033[41mJavaVersionManager\033[0m\033[1m: Failed to delete the original file.");
	}
	if (rename("temp.ini", up) != 0) {
		perror("\033[41mJavaVersionManager\033[0m\033[1m: Failed to rename the temporary file.");
	}
}

void CreateEnvVariable(const char* cwd)
{
	char command[512];
	snprintf(command, sizeof(command), "setx /M Path \"%%Path%%;%s;\"", cwd);
	char fullCommand[600];
	snprintf(fullCommand, sizeof(fullCommand), "cmd.exe /C %s", command);
	STARTUPINFOA si;
	PROCESS_INFORMATION pi;
	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	ZeroMemory(&pi, sizeof(pi));
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;
	HINSTANCE result = ShellExecuteA(
		NULL,
		"runas",
		"cmd.exe",
		fullCommand,
		NULL,
		SW_HIDE
	);
	if ((intptr_t)result <= 32) {
		IfRunAsAdmin = 0;
	}
	else {
		IfRunAsAdmin = 1;
	}
}

DWORD WINAPI ThreadFunction2(LPVOID lpParam) {
	const char* cwd = (const char*)lpParam;
	CreateEnvVariable(cwd);
	return 0;
}

int CommandInterpreter(int paramCount, char* command[])
{
	if (paramCount == 1)
	{
		prthp();
	}
	else
	{
		if (paramCount == 2)
		{
			if (strcmp(command[1], "-version") == 0)
			{
				printf("\nJavaVersionManager: Version 1.0.0		2024-11-16 released\n");
			}
			else if (strcmp(command[1], "-versions") == 0)
			{
				system("java -version");
			}
			else if (strcmp(command[1], "-help") == 0)
			{
				prthp();
			}
			else if (strcmp(command[1], "-list") == 0)
			{
				char filePath[0x400];
				snprintf(filePath, sizeof(filePath), "%s\\JavaVersionManager.ini", up);
				FILE* file;
				errno_t err = fopen_s(&file, filePath, "r");
				if (err != 0) {
					printf("\033[41mJavaVersionManager\033[0m\033[1m: Something wrong happended.\n");
					return 0;
				}
				else {
					char line[0x100];
					putchar('\n');
					while (fgets(line, sizeof(line), file)) {
						if (line[0] != '#' && line[0] != '\n') {
							printf("%s", line);
						}
					}
					putchar('\n');
					fclose(file);
				}
			}
			else if (strcmp(command[1], "-set-ev") == 0)
			{
				char cwd[1024];
				if (_getcwd(cwd, sizeof(cwd)) != NULL) {
					HANDLE hThread = CreateThread(NULL, 0, ThreadFunction2, (LPVOID)cwd, 0, NULL);
					if (hThread == NULL) {
						printf("\n\033[41mJavaVersionManager Exception\033[0m\033[1m: Failed to create thread. Error code:%lu\n", GetLastError());
						return 1;
					}
					WaitForSingleObject(hThread, INFINITE);
					CloseHandle(hThread);
					if (IfRunAsAdmin == 0)
					{
						printf("\n\033[41mJavaVersionManager Exception\033[0m\033[1m: Failed to set environment variable. Please run this command as administrator.\n");
					}
					else
					{
						printf("\nEnvironment variable has been set successfully.\n");
						IfRunAsAdmin = 0;
					}
				}
				else {
					perror("\033[41mJavaVersionManager Exception\033[0m\033[1m: Failed to get current working directory.");
					return 1;
				}
			}
			else
			{
				printf("\n\033[41mJavaVersionManager Exception\033[0m\033[1m: Unknown command.\n");
			}
		}
		else if (paramCount == 3)
		{
			if (strcmp(command[1], "-set") == 0)
			{
				if (!isPureDigit(command[2])) {
					printf("\033[41mJavaVersionManager Exception\033[0m\033[1m: Invalid version number. Please provide a numeric version.\n");
					return 0;
				}
				char filePath[0x400];
				snprintf(filePath, sizeof(filePath), "%s\\JavaVersionManager.ini", up);
				FILE* file;
				errno_t err = fopen_s(&file, filePath, "r");
				if (err != 0) {
					printf("\033[41mJavaVersionManager Exception\033[0m\033[1m: Something wrong happened.\n");
					return 0;
				}
				else {
					char line[0x100];
					int versionFound = 0;
					char version[4] = { 0 };
					char jdkPath[0x400];
					while (fgets(line, sizeof(line), file)) {
						if (line[0] == '[') {
							sscanf_s(line, "[%3s]", version, (unsigned)_countof(version));
							version[strcspn(version, "]")] = '\0';
							if (strcmp(version, command[2]) == 0) {
								if (fgets(jdkPath, sizeof(jdkPath), file) != NULL) {
									printf("\nJDK Path for version %s: \n%s\n", command[2], jdkPath);
									versionFound = 1;
									HANDLE hThread = CreateThread(NULL, 0, ThreadFunction, (LPVOID)jdkPath, 0, NULL);
									if (hThread == NULL) {
										printf("\n\033[41mJavaVersionManager Exception\033[0m\033[1m: Failed to create thread. Error code:%lu\n", GetLastError());
										return 1;
									}
									WaitForSingleObject(hThread, INFINITE);
									CloseHandle(hThread);
									if (IfRunAsAdmin == 0) {
										printf("\n\033[41mJavaVersionManager Exception\033[0m\033[1m: Failed to set JDK Path. Please run this command as administrator.\n");
									}
									else {
										printf("\nJDK Path for version %s has been set successfully.\n", command[2]);
										IfRunAsAdmin = 0;
									}
								}
								else {
									printf("\n\033[41mJavaVersionManager Exception\033[0m\033[1m: \nVersion specified but no path found. Please check your configuration file at %s\\JavaVersionManager.ini.\n", up);
									versionFound = 1;
								}
								break;
							}
						}
					}
					if (!versionFound) {
						printf("\033[41mno such a version\033[0m\033[1m\n");
					}
					fclose(file);
				}
			}
			else if (strcmp(command[1], "-remove") == 0)
			{
				char filePath[0x400];
				snprintf(filePath, sizeof(filePath), "%s\\JavaVersionManager.ini", up);
				FILE* file;
				errno_t err = fopen_s(&file, filePath, "r");
				if (err != 0) {
					printf("\033[41mJavaVersionManager Exception\033[0m\033[1m: Something wrong happened.\n");
					return 0;
				}
				FILE* tempFile;
				fopen_s(&tempFile, "temp.ini", "w");
				if (tempFile == NULL) {
					printf("\033[41mJavaVersionManager Exception\033[0m\033[1m: Cannot create temporary file.\n");
					fclose(file);
					return 0;
				}
				char line[0x100];
				int versionFound = 0;
				char version[4] = { 0 };
				while (fgets(line, sizeof(line), file)) {
					if (line[0] == '[') {
						sscanf_s(line, "[%3s]", version, (unsigned)_countof(version));
						version[strcspn(version, "]")] = '\0';

						if (strcmp(version, command[2]) == 0) {
							versionFound = 1;
							fgets(line, sizeof(line), file);
							continue;
						}
					}
					fputs(line, tempFile);
				}
				fclose(file);
				fclose(tempFile);
				remove(filePath);
				rename("temp.ini", filePath);
				if (versionFound) {
					printf("\nVersion %s has been removed successfully.\n", command[2]);
				}
				else {
					printf("\n\033[41mNo such a version was found.\033[0m\033[1m\n");
					remove("temp.ini");
					
				}
				remove_empty_lines();
			}
			else
			{
				printf("\n\033[41mJavaVersionManager Exception\033[0m\033[1m: Unknown command.\n");
			}
		}
		else if (paramCount == 4)
		{
			if (strcmp(command[1], "-add") == 0)
			{
				if (GetFileAttributesA(command[2]) == INVALID_FILE_ATTRIBUTES) {
					printf("\033[41mJavaVersionManager Exception\033[0m\033[1m: Invalid path.\n");
					return 0;
				}
				if (!isPureDigit(command[3])) {
					printf("\033[41mJavaVersionManager Exception\033[0m\033[1m: Invalid version number. Please provide a numeric version.\n");
					return 0;
				}
				char filePath[0x400];
				snprintf(filePath, sizeof(filePath), "%s\\JavaVersionManager.ini", up);
				FILE* file;
				errno_t err = fopen_s(&file, filePath, "r");
				if (err != 0) {
					printf("\033[41mJavaVersionManager Exception\033[0m\033[1m: Something wrong happened.\n");
					return 0;
				}
				char line[0x100];
				int versionFound = 0;
				char version[4] = { 0 };
				while (fgets(line, sizeof(line), file)) {
					if (line[0] == '[') {
						sscanf_s(line, "[%3s]", version, (unsigned)_countof(version));
						version[strcspn(version, "]")] = '\0';

						if (strcmp(version, command[3]) == 0) {
							versionFound = 1;
							break;
						}
					}
				}
				if (versionFound) {
					printf("JavaVersionManager Exception: Version already exists.\n");
					return 0;
				}
				fclose(file);
				err = fopen_s(&file, filePath, "a");
				if (err != 0) {
					printf("\033[41mJavaVersionManager Exception\033[0m\033[1m: Something wrong happened.\n");
					return 0;
				}
				fprintf(file, "\n[%s]\n", command[3]);
				fprintf(file, "%s", command[2]);
				fclose(file);
				printf("\nVersion %s has been added successfully.\n", command[3]);
				remove_empty_lines();
			}
		}
	}
	return 0;
}

int main(int argc, char* argv[])
{
	if (getUserProfile() != 0) {
		return 1;
	}

	char filePath[0x400];
	snprintf(filePath, sizeof(filePath), "%s\\JavaVersionManager.ini", up);
	FILE* file;
	errno_t err = fopen_s(&file, filePath, "r");
	if (err != 0)
	{
		if (InitConfigFile() != 0) {
			return 1;
		}
	}
	else
	{
		fclose(file);
	}

	CommandInterpreter(argc, argv);

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值