mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-13 05:46:59 -04:00
Fix 2338 自定义命令问题 (#2339)
* Fix 2338 * Fix: Now HMCL could read Post exit command from config file. * Invoke processListener.onExit before invoking exit command. Remove 'throw new RuntimeException'.
This commit is contained in:
parent
372b6376fc
commit
c74ef3eca8
@ -844,6 +844,7 @@ public final class VersionSetting implements Cloneable {
|
||||
vs.setHeight(Optional.ofNullable(obj.get("height")).map(JsonElement::getAsJsonPrimitive).map(this::parseJsonPrimitive).orElse(0));
|
||||
vs.setJavaDir(Optional.ofNullable(obj.get("javaDir")).map(JsonElement::getAsString).orElse(""));
|
||||
vs.setPreLaunchCommand(Optional.ofNullable(obj.get("precalledCommand")).map(JsonElement::getAsString).orElse(""));
|
||||
vs.setPostExitCommand(Optional.ofNullable(obj.get("postExitCommand")).map(JsonElement::getAsString).orElse(""));
|
||||
vs.setServerIp(Optional.ofNullable(obj.get("serverIp")).map(JsonElement::getAsString).orElse(""));
|
||||
vs.setJava(Optional.ofNullable(obj.get("java")).map(JsonElement::getAsString).orElse(""));
|
||||
vs.setWrapper(Optional.ofNullable(obj.get("wrapper")).map(JsonElement::getAsString).orElse(""));
|
||||
|
@ -217,6 +217,7 @@ public final class AdvancedVersionSettingPage extends StackPane implements Decor
|
||||
FXUtils.bindString(txtEnvironmentVariables, versionSetting.environmentVariablesProperty());
|
||||
FXUtils.bindString(txtWrapper, versionSetting.wrapperProperty());
|
||||
FXUtils.bindString(txtPreLaunchCommand, versionSetting.preLaunchCommandProperty());
|
||||
FXUtils.bindString(txtPostExitCommand, versionSetting.postExitCommandProperty());
|
||||
FXUtils.bindEnum(cboRenderer, versionSetting.rendererProperty());
|
||||
noGameCheckPane.selectedProperty().bindBidirectional(versionSetting.notCheckGameProperty());
|
||||
noJVMCheckPane.selectedProperty().bindBidirectional(versionSetting.notCheckJVMProperty());
|
||||
|
@ -419,6 +419,9 @@ public class DefaultLauncher extends Launcher {
|
||||
|
||||
// To guarantee that when failed to generate launch command line, we will not call pre-launch command
|
||||
List<String> rawCommandLine = command.commandLine.asList();
|
||||
if (StringUtils.isNotBlank(options.getWrapper())) {
|
||||
rawCommandLine.addAll(0, StringUtils.parseCommand(options.getWrapper(), getEnvVars()));
|
||||
}
|
||||
|
||||
if (command.tempNativeFolder != null) {
|
||||
Files.deleteIfExists(command.tempNativeFolder);
|
||||
@ -439,7 +442,7 @@ public class DefaultLauncher extends Launcher {
|
||||
File runDirectory = repository.getRunDirectory(version.getId());
|
||||
|
||||
if (StringUtils.isNotBlank(options.getPreLaunchCommand())) {
|
||||
ProcessBuilder builder = new ProcessBuilder(StringUtils.tokenize(options.getPreLaunchCommand())).directory(runDirectory);
|
||||
ProcessBuilder builder = new ProcessBuilder(StringUtils.parseCommand(options.getPreLaunchCommand(), getEnvVars())).directory(runDirectory);
|
||||
builder.environment().putAll(getEnvVars());
|
||||
SystemUtils.callExternalProcess(builder);
|
||||
}
|
||||
@ -649,7 +652,7 @@ public class DefaultLauncher extends Launcher {
|
||||
throw new ExecutionPolicyLimitException();
|
||||
}
|
||||
|
||||
private static void startMonitors(ManagedProcess managedProcess, ProcessListener processListener, Charset encoding, boolean isDaemon) {
|
||||
private void startMonitors(ManagedProcess managedProcess, ProcessListener processListener, Charset encoding, boolean isDaemon) {
|
||||
processListener.setProcess(managedProcess);
|
||||
Thread stdout = Lang.thread(new StreamPump(managedProcess.getProcess().getInputStream(), it -> {
|
||||
processListener.onLog(it, false);
|
||||
@ -661,7 +664,19 @@ public class DefaultLauncher extends Launcher {
|
||||
managedProcess.addLine(it);
|
||||
}, encoding), "stderr-pump", isDaemon);
|
||||
managedProcess.addRelatedThread(stderr);
|
||||
managedProcess.addRelatedThread(Lang.thread(new ExitWaiter(managedProcess, Arrays.asList(stdout, stderr), processListener::onExit), "exit-waiter", isDaemon));
|
||||
managedProcess.addRelatedThread(Lang.thread(new ExitWaiter(managedProcess, Arrays.asList(stdout, stderr), (exitCode, exitType) -> {
|
||||
processListener.onExit(exitCode, exitType);
|
||||
|
||||
if (StringUtils.isNotBlank(options.getPostExitCommand())) {
|
||||
try {
|
||||
ProcessBuilder builder = new ProcessBuilder(StringUtils.parseCommand(options.getPostExitCommand(), getEnvVars())).directory(options.getGameDir());
|
||||
builder.environment().putAll(getEnvVars());
|
||||
SystemUtils.callExternalProcess(builder);
|
||||
} catch (Throwable e) {
|
||||
LOG.log(Level.WARNING, "An Exception happened while running exit command.", e);
|
||||
}
|
||||
}
|
||||
}), "exit-waiter", isDaemon));
|
||||
}
|
||||
|
||||
private static final class Command {
|
||||
|
@ -210,19 +210,58 @@ public final class StringUtils {
|
||||
public static List<String> tokenize(String str) {
|
||||
if (str == null)
|
||||
return new ArrayList<>();
|
||||
else
|
||||
return tokenize(str, " \t\n\r\f");
|
||||
else {
|
||||
// Split the string with ' or " and space cleverly.
|
||||
|
||||
final char groupSplit;
|
||||
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
|
||||
groupSplit = '"';
|
||||
} else {
|
||||
groupSplit = '\'';
|
||||
}
|
||||
|
||||
public static List<String> tokenize(String str, String delim) {
|
||||
ArrayList<String> result = new ArrayList<>();
|
||||
StringTokenizer tokenizer = new StringTokenizer(str, delim);
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
delim = tokenizer.nextToken();
|
||||
result.add(delim);
|
||||
ArrayList<String> parts = new ArrayList<>();
|
||||
|
||||
{
|
||||
boolean inside = false;
|
||||
StringBuilder current = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char c = str.charAt(i);
|
||||
if (c == groupSplit) {
|
||||
inside = !inside;
|
||||
} else if (!inside && c == ' ') {
|
||||
parts.add(current.toString());
|
||||
current.setLength(0);
|
||||
} else {
|
||||
current.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
if (current.length() != 0) {
|
||||
parts.add(current.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> parseCommand(String command, Map<String, String> env) {
|
||||
StringBuilder stringBuilder = new StringBuilder(command);
|
||||
env.forEach((key, value) -> {
|
||||
key = "$" + key;
|
||||
int i = 0;
|
||||
while (true) {
|
||||
i = stringBuilder.indexOf(key, i);
|
||||
if (i == -1) {
|
||||
break;
|
||||
}
|
||||
stringBuilder.replace(i, i + key.length(), value);
|
||||
}
|
||||
});
|
||||
|
||||
return tokenize(stringBuilder.toString());
|
||||
}
|
||||
|
||||
public static String parseColorEscapes(String original) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user