Skip to content

Commit b9c7fd2

Browse files
committed
Fix background saving on Windows
1 parent 8475cbc commit b9c7fd2

File tree

4 files changed

+114
-37
lines changed

4 files changed

+114
-37
lines changed

src/main/java/airsquared/blobsaver/app/Background.java

Lines changed: 82 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,8 @@
2626
import java.io.UncheckedIOException;
2727
import java.nio.file.Files;
2828
import java.nio.file.Path;
29-
import java.text.SimpleDateFormat;
3029
import java.util.ArrayList;
3130
import java.util.Collections;
32-
import java.util.Date;
3331
import java.util.function.Predicate;
3432

3533
class Background {
@@ -41,7 +39,6 @@ class Background {
4139

4240

4341
private static void macosBackgroundFile() {
44-
String executablePath = Utils.getBlobsaverExecutable().getAbsolutePath();
4542
long interval = Prefs.getBackgroundTimeUnit().toSeconds(Prefs.getBackgroundInterval());
4643
//language=XML
4744
String plist = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
@@ -52,7 +49,7 @@ private static void macosBackgroundFile() {
5249
"<string>" + backgroundLabel + "</string>" +
5350
"<key>ProgramArguments</key>" +
5451
"<array>" +
55-
" <string>" + executablePath + "</string>" +
52+
" <string>" + executablePath() + "</string>" +
5653
" <string>--background-autosave</string>" +
5754
"</array>" +
5855
"<key>RunAtLoad</key>" +
@@ -70,25 +67,24 @@ private static void macosBackgroundFile() {
7067
}
7168

7269
private static void linuxBackgroundFile() {
73-
String executablePath = Utils.getBlobsaverExecutable().getAbsolutePath();
7470
String service = """
7571
[Unit]
76-
Description=Run blobsaver autosave
72+
Description=Save blobs in the background
7773
7874
[Service]
7975
Type=oneshot
80-
ExecStart=%s --background-autosave""".formatted(executablePath);
76+
ExecStart=%s --background-autosave""".formatted(executablePath());
8177
String timer = """
8278
[Unit]
83-
Description=Run blobsaver autosave
79+
Description=Save blobs in the background
8480
8581
[Timer]
8682
OnBootSec=1min
8783
OnUnitInactiveSec=%dmin
8884
8985
[Install]
9086
WantedBy=timers.target
91-
""".formatted(Prefs.getBackgroundTimeUnit().toMinutes(Prefs.getBackgroundInterval()));
87+
""".formatted(Prefs.getBackgroundIntervalMinutes());
9288
String dataHome = System.getenv("XDG_DATA_HOME");
9389
if (dataHome == null) {
9490
dataHome = System.getProperty("user.home") + "/.local/share";
@@ -102,16 +98,84 @@ private static void linuxBackgroundFile() {
10298
}
10399
}
104100

101+
private static Path windowsBackgroundFile() {
102+
String xml = """
103+
<?xml version="1.0" encoding="UTF-16"?>
104+
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
105+
<RegistrationInfo>
106+
<Author>airsquared</Author>
107+
<Description>Save blobs in the background</Description>
108+
<URI>%1$s</URI>
109+
</RegistrationInfo>
110+
<Triggers>
111+
<LogonTrigger>
112+
<Repetition>
113+
<Interval>PT%2$dM</Interval>
114+
<StopAtDurationEnd>false</StopAtDurationEnd>
115+
</Repetition>
116+
<Enabled>true</Enabled>
117+
<UserId>%3$s</UserId>
118+
</LogonTrigger>
119+
<RegistrationTrigger>
120+
<Repetition>
121+
<Interval>PT%2$dM</Interval>
122+
<StopAtDurationEnd>false</StopAtDurationEnd>
123+
</Repetition>
124+
<Enabled>true</Enabled>
125+
</RegistrationTrigger>
126+
</Triggers>
127+
<Principals>
128+
<Principal id="Author">
129+
<UserId>%3$s</UserId>
130+
<LogonType>InteractiveToken</LogonType>
131+
<RunLevel>LeastPrivilege</RunLevel>
132+
</Principal>
133+
</Principals>
134+
<Settings>
135+
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
136+
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
137+
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
138+
<AllowHardTerminate>true</AllowHardTerminate>
139+
<StartWhenAvailable>true</StartWhenAvailable>
140+
<RunOnlyIfNetworkAvailable>true</RunOnlyIfNetworkAvailable>
141+
<IdleSettings>
142+
<StopOnIdleEnd>false</StopOnIdleEnd>
143+
<RestartOnIdle>false</RestartOnIdle>
144+
</IdleSettings>
145+
<AllowStartOnDemand>true</AllowStartOnDemand>
146+
<Enabled>true</Enabled>
147+
<Hidden>false</Hidden>
148+
<RunOnlyIfIdle>false</RunOnlyIfIdle>
149+
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
150+
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
151+
<WakeToRun>false</WakeToRun>
152+
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
153+
<Priority>7</Priority>
154+
</Settings>
155+
<Actions Context="Author">
156+
<Exec>
157+
<Command>"%4$s"</Command>
158+
<Arguments>--background-autosave</Arguments>
159+
</Exec>
160+
</Actions>
161+
</Task>
162+
""".formatted(windowsTaskName, Prefs.getBackgroundIntervalMinutes(), System.getProperty("user.name"), executablePath());
163+
try {
164+
Path path = Files.createTempFile("blobsaver_background_service", ".xml");
165+
Files.writeString(path, xml);
166+
return path;
167+
} catch (IOException e) {
168+
throw new UncheckedIOException(e);
169+
}
170+
171+
}
172+
105173
public static void startBackground() {
106174
if (Platform.isMac()) {
107175
macosBackgroundFile();
108176
launchctl("load", "-w", plistFilePath.toString());
109177
} else if (Platform.isWindows()) {
110-
// https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks-create
111-
schtasks("/create", "/it", "/f", "/tn", windowsTaskName,
112-
"/tr", Utils.getBlobsaverExecutable().getAbsolutePath() + " --background-autosave",
113-
"/sc", "once", "/st", new SimpleDateFormat("HH:mm").format(new Date()),
114-
"/ri", Long.toString(Prefs.getBackgroundTimeUnit().toMinutes(Prefs.getBackgroundInterval())));
178+
schtasks("/create", "/xml", windowsBackgroundFile().toString(), "/f", "/tn", windowsTaskName);
115179
} else {
116180
linuxBackgroundFile();
117181
systemctl("daemon-reload");
@@ -157,6 +221,10 @@ public static void runOnce() {
157221
}
158222
}
159223

224+
private static String executablePath() {
225+
return Utils.getBlobsaverExecutable().getAbsolutePath();
226+
}
227+
160228
private static void launchctl(String... args) {
161229
execute("launchctl", args);
162230
}

src/main/java/airsquared/blobsaver/app/Controller.java

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,8 @@ public void deleteDeviceHandler() {
228228
Prefs.SavedDevice device = deviceList.getSelectionModel().getSelectedItem();
229229
if (device == null) return;
230230

231-
Alert alert = new Alert(Alert.AlertType.CONFIRMATION,
232-
"Are you sure you would like to remove the device \"" + device + "\"?");
233-
alert.showAndWait();
234-
if (ButtonType.OK.equals(alert.getResult())) {
231+
ButtonType result = Utils.showConfirmAlert("Are you sure you would like to remove the device \"" + device + "\"?");
232+
if (ButtonType.OK.equals(result)) {
235233
device.delete();
236234
}
237235
}
@@ -412,9 +410,7 @@ public void chooseTimeToRunHandler() {
412410
return;
413411
}
414412
if (Background.isBackgroundEnabled()) {
415-
Alert restartBackgroundAlert = new Alert(Alert.AlertType.INFORMATION,
416-
"You will need to restart the background for changes to take effect.", new ButtonType("Stop Background"));
417-
restartBackgroundAlert.showAndWait();
413+
Utils.showInfoAlert("You will need to restart the background for changes to take effect.", new ButtonType("Stop Background"));
418414
startBackgroundButton.fire();
419415
}
420416
}
@@ -425,10 +421,12 @@ public void startBackgroundHandler() {
425421
updateBackgroundSettings();
426422
} else {
427423
Background.startBackground();
428-
updateBackgroundSettings();
429-
Alert alert = new Alert(Alert.AlertType.INFORMATION,
430-
"Background saving has been enabled. You can now close this application and it will continue saving blobs at the interval you set, and won't use any resources when it is not running.", ButtonType.OK);
431-
alert.showAndWait();
424+
if (Background.isBackgroundEnabled()) {
425+
updateBackgroundSettings();
426+
Utils.showInfoAlert("A background saving task has been scheduled. You can now quit this application, and blobs will continue to be saved at the interval you set.");
427+
} else {
428+
Utils.showUnreportableError("Background saving is not enabled. Try again with the debug log open to check for any errors.");
429+
}
432430
}
433431
}
434432

@@ -437,15 +435,12 @@ public void forceCheckForBlobsHandler() {
437435
}
438436

439437
public void resetAppHandler() {
440-
Alert confirmationAlert = new Alert(Alert.AlertType.CONFIRMATION, "Are you sure you would like to reset/remove all blobsaver data?");
441-
confirmationAlert.showAndWait();
442-
if (confirmationAlert.getResult() == null || ButtonType.CANCEL.equals(confirmationAlert.getResult())) {
443-
return;
438+
ButtonType result = Utils.showConfirmAlert("Are you sure you would like to reset/remove all blobsaver data?");
439+
if (ButtonType.OK.equals(result)) {
440+
Prefs.resetPrefs();
441+
Utils.showInfoAlert("The application data have been removed. \nThe application will now exit.");
442+
Main.exit();
444443
}
445-
Prefs.resetPrefs();
446-
Alert applicationCloseAlert = new Alert(Alert.AlertType.INFORMATION, "The application data have been removed. \nThe application will now exit.", ButtonType.OK);
447-
applicationCloseAlert.showAndWait();
448-
Main.exit();
449444
}
450445

451446
public void exportSavedDevices() {
@@ -474,9 +469,8 @@ public void importFromXML() {
474469
}
475470

476471
public void importFromOldVersion() {
477-
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "Continuing will import all presets into saved devices from blobsaver version 2.5.5 and older.");
478-
alert.showAndWait();
479-
if (ButtonType.OK.equals(alert.getResult())) {
472+
ButtonType result = Utils.showConfirmAlert("Continuing will import all presets into saved devices from blobsaver version 2.5.5 and older.");
473+
if (ButtonType.OK.equals(result)) {
480474
Prefs.importOldVersion();
481475
}
482476
}

src/main/java/airsquared/blobsaver/app/Prefs.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ public static TimeUnit getBackgroundTimeUnit() {
152152
return TimeUnit.valueOf(appPrefs.get("Time unit for background", "DAYS"));
153153
}
154154

155+
public static long getBackgroundIntervalMinutes() {
156+
return getBackgroundTimeUnit().toMinutes(getBackgroundInterval());
157+
}
158+
155159
public static class SavedDevice {
156160
private final Preferences node;
157161

src/main/java/airsquared/blobsaver/app/Utils.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,21 @@ static void showReportableError(String msg, String toCopy) {
254254
}
255255

256256
static void showUnreportableError(String msg) {
257-
Alert alert = new Alert(Alert.AlertType.ERROR, msg, ButtonType.OK);
257+
Alert alert = new Alert(Alert.AlertType.ERROR, msg);
258258
alert.showAndWait();
259259
}
260260

261+
static void showInfoAlert(String msg, ButtonType... buttons) {
262+
Alert alert = new Alert(Alert.AlertType.INFORMATION, msg, buttons);
263+
alert.showAndWait();
264+
}
265+
266+
static ButtonType showConfirmAlert(String msg) {
267+
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, msg);
268+
alert.showAndWait();
269+
return alert.getResult();
270+
}
271+
261272
static void copyToClipboard(String s) {
262273
ClipboardContent clipboardContent = new ClipboardContent();
263274
clipboardContent.putString(s);

0 commit comments

Comments
 (0)