浏览代码

Added autostart support for windows
fixes #418

Sebastian Stenzel 5 年之前
父节点
当前提交
11ffec862e

+ 2 - 2
main/ui/src/main/java/org/cryptomator/ui/preferences/AutoStartModule.java

@@ -16,8 +16,8 @@ abstract class AutoStartModule {
 		if (SystemUtils.IS_OS_MAC_OSX && macFunctions.isPresent()) {
 			return Optional.of(new AutoStartMacStrategy(macFunctions.get()));
 		} else if (SystemUtils.IS_OS_WINDOWS) {
-			// TODO: add windows support
-			return Optional.empty();
+			Optional<String> exeName = ProcessHandle.current().info().command();
+			return exeName.map(AutoStartWinStrategy::new);
 		} else {
 			return Optional.empty();
 		}

+ 91 - 0
main/ui/src/main/java/org/cryptomator/ui/preferences/AutoStartWinStrategy.java

@@ -0,0 +1,91 @@
+package org.cryptomator.ui.preferences;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+class AutoStartWinStrategy implements AutoStartStrategy {
+
+	private static final Logger LOG = LoggerFactory.getLogger(AutoStartWinStrategy.class);
+	private static final String HKCU_AUTOSTART_KEY = "\"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\"";
+	private static final String AUTOSTART_VALUE = "Cryptomator";
+	private final String exePath;
+
+	public AutoStartWinStrategy(String exePath) {
+		this.exePath = exePath;
+	}
+
+	@Override
+	public CompletionStage<Boolean> isAutoStartEnabled() {
+		ProcessBuilder regQuery = new ProcessBuilder("reg", "query", HKCU_AUTOSTART_KEY, //
+				"/v", AUTOSTART_VALUE);
+		try {
+			Process proc = regQuery.start();
+			return proc.onExit().thenApply(p -> p.exitValue() == 0);
+		} catch (IOException e) {
+			LOG.warn("Failed to query registry value {}{}", HKCU_AUTOSTART_KEY, AUTOSTART_VALUE);
+			return CompletableFuture.completedFuture(false);
+		}
+	}
+
+	@Override
+	public void enableAutoStart() throws TogglingAutoStartFailedException {
+		ProcessBuilder regAdd = new ProcessBuilder("reg", "add", HKCU_AUTOSTART_KEY, //
+				"/v", AUTOSTART_VALUE, //
+				"/t", "REG_SZ", //
+				"/d", "\"" + exePath + "\"", //
+				"/f");
+		String command = regAdd.command().stream().collect(Collectors.joining(" "));
+		try {
+			Process proc = regAdd.start();
+			boolean finishedInTime = waitForProcess(proc, 5, TimeUnit.SECONDS);
+			if (finishedInTime) {
+				LOG.debug("Added registry value {}{}.", HKCU_AUTOSTART_KEY, AUTOSTART_VALUE);
+			} else {
+				throw new TogglingAutoStartFailedException("Adding registry value failed.");
+			}
+		} catch (IOException e) {
+			throw new TogglingAutoStartFailedException("Adding registry value failed. " + command, e);
+		}
+	}
+
+	@Override
+	public void disableAutoStart() throws TogglingAutoStartFailedException {
+		ProcessBuilder regRemove = new ProcessBuilder("reg", "delete", HKCU_AUTOSTART_KEY, //
+				"/v", AUTOSTART_VALUE, //
+				"/f");
+		String command = regRemove.command().stream().collect(Collectors.joining(" "));
+		try {
+			Process proc = regRemove.start();
+			boolean finishedInTime = waitForProcess(proc, 5, TimeUnit.SECONDS);
+			if (finishedInTime) {
+				LOG.debug("Removed registry value {}{}.", HKCU_AUTOSTART_KEY, AUTOSTART_VALUE);
+			} else {
+				throw new TogglingAutoStartFailedException("Removing registry value failed.");
+			}
+		} catch (IOException e) {
+			throw new TogglingAutoStartFailedException("Removing registry value failed. " + command, e);
+		}
+	}
+
+	private static boolean waitForProcess(Process proc, int timeout, TimeUnit timeUnit) {
+		boolean finishedInTime = false;
+		try {
+			finishedInTime = proc.waitFor(timeout, timeUnit);
+		} catch (InterruptedException e) {
+			LOG.error("Timeout while reading registry", e);
+			Thread.currentThread().interrupt();
+		} finally {
+			if (!finishedInTime) {
+				proc.destroyForcibly();
+			}
+		}
+		return finishedInTime;
+	}
+
+}