Skip to content

Instantly share code, notes, and snippets.

@wagyourtail
Created January 6, 2024 08:15
Show Gist options
  • Save wagyourtail/fd9558d04dcba8d7b429b540f7671ac0 to your computer and use it in GitHub Desktop.
Save wagyourtail/fd9558d04dcba8d7b429b540f7671ac0 to your computer and use it in GitHub Desktop.
archlinux-java but for windows
@echo off
rem run python script and capture output/error code
python windows-java.py %* > "%TEMP%\windows-java-output.txt"
if %ERRORLEVEL% == 1 (
goto Error
)
<"%TEMP%\windows-java-output.txt" (
set /p Var1=
set /p Var2=
set /p Var3=
)
if %Var1% == set (
rem set JAVA_HOME and PATH for current session
set "JAVA_HOME=%Var2%"
set "PATH=%Var3%"
rem set JAVA_HOME and PATH system wide
rem setx JAVA_HOME "%Var2%"
rem setx PATH "%Var3%"
rem debug
rem echo JAVA_HOME=%Var2%
rem echo PATH=%Var3%
echo Successfully set JAVA to use %Var2%
) else (
rem skip first line
for /f "skip=1 tokens=*" %%a in (%TEMP%\windows-java-output.txt) do (
echo. %%a
)
)
goto End
: Error
for /f "tokens=*" %%a in (%TEMP%\windows-java-output.txt) do (
echo. %%a
)
:End
import argparse
import sys
import os
import winreg
class JavaInstall:
def __init__(self, version: str, arch: str, java_home: str, short_name: str):
self.version = version
self.arch = arch
self.java_home = java_home
self.short_name = short_name
def __str__(self) -> str:
return f"{self.shortName():30s} ({self.java_home})"
def realVersion(self) -> str:
if self.version.startswith("1."):
return self.version[2:]
else:
return self.version
def majorVersion(self) -> str:
return self.realVersion().split(".")[0]
def javaPath(self) -> str:
return self.java_home + "\\bin\\java.exe"
def shortName(self):
# if arch != system arch then add arch to name
if self.arch != "x64":
return f"java-{self.majorVersion()}-{self.short_name}-{self.arch}"
else:
return f"java-{self.majorVersion()}-{self.short_name}"
def checkExists(self) -> bool:
return os.path.exists(self.javaPath())
def main(*args: str) -> None:
parser = argparse.ArgumentParser(
prog="windows-java",
description="CLI tool to manage Java installs on Windows.",
add_help=False
)
subparsers = parser.add_subparsers(help="COMMAND", required=True, dest="command")
# status
status_parser = subparsers.add_parser(
"status",
help="List installed Java environments and enabled one",
)
# get
get_parser = subparsers.add_parser(
"get",
help="Return the short name of the Java environment set as default",
)
# set
set_parser = subparsers.add_parser(
"set",
help="Force <JAVA_ENV> as default",
)
set_parser.add_argument(
"java_env",
help="The short name of the Java environment to set as default"
)
# if no args, set default to print help
if not args:
parser.print_help()
sys.exit(1)
args = parser.parse_args(args)
# match case on command
match args.command:
case "status":
status()
case "get":
get()
case "set":
set_(args.java_env)
case _:
raise AssertionError("argparse should have caught this")
def getJavaInstalls() -> list[JavaInstall]:
# check registry
check_installs: list[list[JavaInstall]] = [
# oracle 8
check_registry("Oracle JRE", winreg.KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment",
"JavaHome"),
check_registry("Oracle JDK", winreg.KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome"),
check_registry("Oracle JRE", winreg.KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment",
"JavaHome"),
check_registry("Oracle JDK", winreg.KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome"),
# oracle 9+
check_registry("Oracle JRE", winreg.KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome"),
check_registry("Oracle JDK", winreg.KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome"),
check_registry("Oracle JRE", winreg.KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome"),
check_registry("Oracle JDK", winreg.KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome"),
# adopt open jdk
check_registry("Adoptium JRE", winreg.KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI"),
check_registry("Adoptium JDK", winreg.KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI"),
check_registry("Adoptium JRE", winreg.KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI"),
check_registry("Adoptium JDK", winreg.KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI"),
# eclipse foundation
check_registry("Eclipse JDK", winreg.KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path",
"\\hotspot\\MSI"),
check_registry("Eclipse JDK", winreg.KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path",
"\\hotspot\\MSI"),
# eclipse adoptium
check_registry("Eclipse Adoptium JRE", winreg.KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JRE", "Path",
"\\hotspot\\MSI"),
check_registry("Eclipse Adoptium JDK", winreg.KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path",
"\\hotspot\\MSI"),
check_registry("Eclipse Adoptium JRE", winreg.KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JRE", "Path",
"\\hotspot\\MSI"),
check_registry("Eclipse Adoptium JDK", winreg.KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path",
"\\hotspot\\MSI"),
# microsoft
check_registry("Microsoft JRE", winreg.KEY_WOW64_64KEY, "SOFTWARE\\Microsoft\\JDK", "Path", "\\hotspot\\MSI"),
# azul zulu
check_registry("Azul Zulu JRE", winreg.KEY_WOW64_64KEY, "SOFTWARE\\Azul Systems\\Zulu", "Path",
"InstallationPath"),
check_registry("Azul Zulu JRE", winreg.KEY_WOW64_32KEY, "SOFTWARE\\Azul Systems\\Zulu", "Path",
"InstallationPath"),
# bellsoft liberica
check_registry("Bellsoft Liberica JRE", winreg.KEY_WOW64_64KEY, "SOFTWARE\\BellSoft\\LibericaJRE", "Path",
"InstallationPath"),
]
flat_installs = [install for installs in check_installs for install in installs]
# add hardcoded jre 8/7/6 dirs
flat_installs += [
JavaInstall("8", "x64", "C:\\Program Files\\Java\\jre8", "oracle-jre"),
JavaInstall("8", "x86", "C:\\Program Files (x86)\\Java\\jre8", "oracle-jre"),
JavaInstall("7", "x64", "C:\\Program Files\\Java\\jre7", "oracle-jre"),
JavaInstall("7", "x86", "C:\\Program Files (x86)\\Java\\jre7", "oracle-jre"),
JavaInstall("6", "x64", "C:\\Program Files\\Java\\jre6", "oracle-jre"),
JavaInstall("6", "x86", "C:\\Program Files (x86)\\Java\\jre6", "oracle-jre"),
]
# filter existing
flat_installs = list(filter(lambda x: x.checkExists(), flat_installs))
flat_installs.reverse()
# filter out duplicate homes
seen_homes: set[str] = set([])
flat_installs_de_duped = []
for install in flat_installs:
if install.java_home not in seen_homes:
flat_installs_de_duped.append(install)
seen_homes.add(install.java_home)
# then sort by version, and prioritize x64
flat_installs_de_duped.sort(key=lambda install: (install.realVersion(), install.arch))
return flat_installs_de_duped
def check_registry(short_name: str, key_type: int, key_name: str, key_java_dir: str, subkey_suffix: str = "") -> list[
JavaInstall]:
try:
arch_type = "unknown"
if key_type == winreg.KEY_WOW64_64KEY:
arch_type = "x64"
elif key_type == winreg.KEY_WOW64_32KEY:
arch_type = "x86"
registry_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_name, 0,
winreg.KEY_READ | key_type | winreg.KEY_ENUMERATE_SUB_KEYS)
sub, val, mod = winreg.QueryInfoKey(registry_key)
keys: list[JavaInstall] = []
for i in range(sub):
try:
subkey_name = winreg.EnumKey(registry_key, i)
new_key_name = key_name + "\\" + subkey_name + subkey_suffix
new_registry_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, new_key_name, 0,
winreg.KEY_READ | key_type)
(java_dir, _) = winreg.QueryValueEx(new_registry_key, key_java_dir)
keys.append(JavaInstall(subkey_name, arch_type, java_dir, short_name.lower().replace(' ', '-')))
winreg.CloseKey(new_registry_key)
except WindowsError | OSError:
continue
winreg.CloseKey(registry_key)
return keys
except WindowsError | OSError:
return []
def status() -> None:
print("status")
# get java home env var
java_home = os.environ.get("JAVA_HOME", None)
installs = getJavaInstalls()
print("Available Java environments:")
print("current\tshortname\tdirectory")
for install in installs:
if install.java_home == java_home:
print("| -> |", install)
else:
print("| |", install)
if not installs:
print(" No Java environments installed")
def get() -> None:
print("get")
java_home = os.environ.get("JAVA_HOME", None)
installs = getJavaInstalls()
for install in installs:
if install.java_home == java_home:
print(install.shortName())
return
print("No Java environment set, or JAVA_HOME was not found via other means")
def set_java_bin_in_path(java_home: str, installs: list[JavaInstall]) -> str:
path = []
path.append(os.path.realpath(java_home + "\\bin"))
# enumerate java home dirs
bins = set([os.path.realpath(install.java_home + "\\bin") for install in installs])
for element in os.environ["PATH"].split(os.pathsep):
if os.path.realpath(element) not in bins:
path.append(element)
return os.pathsep.join(path)
def set_(java_env: str) -> None:
print("set")
installs = getJavaInstalls()
clean_java_env = " ".join(str(java_env).split())
for install in installs:
if " ".join(str(install).split()).startswith(clean_java_env):
print(install.java_home)
# calculate new env path var
print(set_java_bin_in_path(install.java_home, installs))
return
print(f"Java environment '{clean_java_env}' not found")
sys.exit(1)
if __name__ == "__main__":
main(*sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment