Compare commits
3 Commits
24b9e0aa80
...
v0.1.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 16ce906044 | |||
| a24d49f463 | |||
| e7e533d8c6 |
@@ -1,7 +1,7 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>0.1.0</Version>
|
||||
<Version>0.1.1</Version>
|
||||
<Authors>Justin Paul</Authors>
|
||||
<Company>Justin Paul</Company>
|
||||
<Product>Webhook Server</Product>
|
||||
|
||||
@@ -77,3 +77,41 @@ Filename: "powershell.exe"; \
|
||||
Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{app}\scripts\uninstall-service.ps1"""; \
|
||||
Flags: runhidden; \
|
||||
RunOnceId: "RemoveWebhookService"
|
||||
|
||||
[Code]
|
||||
function ServiceExists(): Boolean;
|
||||
var
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
// sc.exe query returns 0 when the service exists, 1060 when it does not.
|
||||
Exec(ExpandConstant('{sys}\sc.exe'), 'query WebhookServer', '', SW_HIDE,
|
||||
ewWaitUntilTerminated, ResultCode);
|
||||
Result := (ResultCode = 0);
|
||||
end;
|
||||
|
||||
function PrepareToInstall(var NeedsRestart: Boolean): String;
|
||||
var
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
Result := '';
|
||||
|
||||
// 1. If the service exists, stop it so its binaries are unlocked before file
|
||||
// copy. net stop is synchronous (blocks until the service is actually
|
||||
// stopped), unlike sc stop which is fire-and-forget. Non-zero exit -
|
||||
// already stopped, missing, dependency error - we ignore; the file copy
|
||||
// will fail loudly if the binaries are still locked.
|
||||
if ServiceExists() then
|
||||
begin
|
||||
WizardForm.PreparingLabel.Caption := 'Stopping the WebhookServer service...';
|
||||
Exec(ExpandConstant('{sys}\net.exe'), 'stop WebhookServer', '', SW_HIDE,
|
||||
ewWaitUntilTerminated, ResultCode);
|
||||
end;
|
||||
|
||||
// 2. Kill any running GUI / tray instances so their binaries are unlocked too.
|
||||
// /f forces termination, /im matches by image name, "*" wildcard would be
|
||||
// risky so we name them explicitly.
|
||||
Exec(ExpandConstant('{sys}\taskkill.exe'), '/f /im WebhookServer.Gui.exe',
|
||||
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||
Exec(ExpandConstant('{sys}\taskkill.exe'), '/f /im WebhookServer.Service.exe',
|
||||
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||
end;
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
<Separator/>
|
||||
<MenuItem Header="_Import config…" Command="{Binding ImportConfigCommand}"/>
|
||||
<MenuItem Header="_Export config…" Command="{Binding ExportConfigCommand}"/>
|
||||
<MenuItem Header="_Backups"
|
||||
<MenuItem Header="Config _Checkpoints"
|
||||
ItemsSource="{Binding Backups}"
|
||||
ToolTip="Snapshots taken automatically before each save. Click one to restore."
|
||||
SubmenuOpened="OnBackupsSubmenuOpened">
|
||||
<MenuItem.ItemContainerStyle>
|
||||
<Style TargetType="MenuItem">
|
||||
|
||||
@@ -189,7 +189,7 @@ public sealed partial class MainViewModel : ObservableObject
|
||||
foreach (var b in list) Backups.Add(b);
|
||||
});
|
||||
}
|
||||
catch { /* ignore - backup listing isn't critical */ }
|
||||
catch { /* ignore - checkpoint listing isn't critical */ }
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
@@ -197,8 +197,8 @@ public sealed partial class MainViewModel : ObservableObject
|
||||
{
|
||||
if (entry is null) return;
|
||||
var ok = MessageBox.Show(
|
||||
$"Restore configuration from {entry.FileName} ({entry.SavedAt:yyyy-MM-dd HH:mm})?\n\nA backup of the current config will be saved first.",
|
||||
"Restore backup",
|
||||
$"Restore the configuration from the checkpoint taken at {entry.SavedAt:yyyy-MM-dd HH:mm}?\n\nThe current configuration is automatically saved as a new checkpoint first, so you can roll forward again.",
|
||||
"Restore checkpoint",
|
||||
MessageBoxButton.OKCancel,
|
||||
MessageBoxImage.Question);
|
||||
if (ok != MessageBoxResult.OK) return;
|
||||
@@ -249,7 +249,7 @@ public sealed partial class MainViewModel : ObservableObject
|
||||
if (cfg is null) throw new InvalidOperationException("File did not contain a valid config.");
|
||||
|
||||
var ok = MessageBox.Show(
|
||||
$"Replace the current configuration with {dlg.FileName}?\n\nA backup of the current config will be saved first.",
|
||||
$"Replace the current configuration with {dlg.FileName}?\n\nA checkpoint of the current config is saved first, so you can roll back from File → Config Checkpoints.",
|
||||
"Import config",
|
||||
MessageBoxButton.OKCancel,
|
||||
MessageBoxImage.Warning);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<UseWPF>true</UseWPF>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ApplicationIcon>..\..\resources\webhook-server.ico</ApplicationIcon>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<AssemblyTitle>Webhook Server</AssemblyTitle>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="WebhookServer.Gui"/>
|
||||
|
||||
<!-- The GUI talks to the service via a named pipe ACL'd to SYSTEM and the
|
||||
Administrators group. UAC token splitting denies that group on the
|
||||
standard user token, so without elevation the pipe connect fails with
|
||||
"Access is denied". Always run elevated. Start Menu shortcuts and the
|
||||
installer's post-install launch both honor this. -->
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
||||
Reference in New Issue
Block a user