From 11ffec862ecc778efbaf08378774f36fcaf7478e Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 7 Jan 2020 17:56:05 +0100 Subject: [PATCH] Added autostart support for windows fixes #418 --- .../ui/preferences/AutoStartModule.java | 4 +- .../ui/preferences/AutoStartWinStrategy.java | 91 +++++++++++++++++++ 2 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 main/ui/src/main/java/org/cryptomator/ui/preferences/AutoStartWinStrategy.java diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/AutoStartModule.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/AutoStartModule.java index 839043973..d006d8681 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/preferences/AutoStartModule.java +++ b/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 exeName = ProcessHandle.current().info().command(); + return exeName.map(AutoStartWinStrategy::new); } else { return Optional.empty(); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/AutoStartWinStrategy.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/AutoStartWinStrategy.java new file mode 100644 index 000000000..85e8a3e88 --- /dev/null +++ b/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 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; + } + +}