Compare commits
3 Commits
gitea-sync-fix
...
v0.1.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 16ce906044 | |||
| a24d49f463 | |||
| e7e533d8c6 |
@@ -1,7 +1,7 @@
|
|||||||
<Project>
|
<Project>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>0.1.0</Version>
|
<Version>0.1.1</Version>
|
||||||
<Authors>Justin Paul</Authors>
|
<Authors>Justin Paul</Authors>
|
||||||
<Company>Justin Paul</Company>
|
<Company>Justin Paul</Company>
|
||||||
<Product>Webhook Server</Product>
|
<Product>Webhook Server</Product>
|
||||||
|
|||||||
@@ -77,3 +77,41 @@ Filename: "powershell.exe"; \
|
|||||||
Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{app}\scripts\uninstall-service.ps1"""; \
|
Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{app}\scripts\uninstall-service.ps1"""; \
|
||||||
Flags: runhidden; \
|
Flags: runhidden; \
|
||||||
RunOnceId: "RemoveWebhookService"
|
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/>
|
<Separator/>
|
||||||
<MenuItem Header="_Import config…" Command="{Binding ImportConfigCommand}"/>
|
<MenuItem Header="_Import config…" Command="{Binding ImportConfigCommand}"/>
|
||||||
<MenuItem Header="_Export config…" Command="{Binding ExportConfigCommand}"/>
|
<MenuItem Header="_Export config…" Command="{Binding ExportConfigCommand}"/>
|
||||||
<MenuItem Header="_Backups"
|
<MenuItem Header="Config _Checkpoints"
|
||||||
ItemsSource="{Binding Backups}"
|
ItemsSource="{Binding Backups}"
|
||||||
|
ToolTip="Snapshots taken automatically before each save. Click one to restore."
|
||||||
SubmenuOpened="OnBackupsSubmenuOpened">
|
SubmenuOpened="OnBackupsSubmenuOpened">
|
||||||
<MenuItem.ItemContainerStyle>
|
<MenuItem.ItemContainerStyle>
|
||||||
<Style TargetType="MenuItem">
|
<Style TargetType="MenuItem">
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ public sealed partial class MainViewModel : ObservableObject
|
|||||||
foreach (var b in list) Backups.Add(b);
|
foreach (var b in list) Backups.Add(b);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch { /* ignore - backup listing isn't critical */ }
|
catch { /* ignore - checkpoint listing isn't critical */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
@@ -197,8 +197,8 @@ public sealed partial class MainViewModel : ObservableObject
|
|||||||
{
|
{
|
||||||
if (entry is null) return;
|
if (entry is null) return;
|
||||||
var ok = MessageBox.Show(
|
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 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 backup",
|
"Restore checkpoint",
|
||||||
MessageBoxButton.OKCancel,
|
MessageBoxButton.OKCancel,
|
||||||
MessageBoxImage.Question);
|
MessageBoxImage.Question);
|
||||||
if (ok != MessageBoxResult.OK) return;
|
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.");
|
if (cfg is null) throw new InvalidOperationException("File did not contain a valid config.");
|
||||||
|
|
||||||
var ok = MessageBox.Show(
|
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",
|
"Import config",
|
||||||
MessageBoxButton.OKCancel,
|
MessageBoxButton.OKCancel,
|
||||||
MessageBoxImage.Warning);
|
MessageBoxImage.Warning);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<ApplicationIcon>..\..\resources\webhook-server.ico</ApplicationIcon>
|
<ApplicationIcon>..\..\resources\webhook-server.ico</ApplicationIcon>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<AssemblyTitle>Webhook Server</AssemblyTitle>
|
<AssemblyTitle>Webhook Server</AssemblyTitle>
|
||||||
</PropertyGroup>
|
</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