feat(ui): add Restart worker menu entry under Help
Stops and starts the ClaudeDoWorker Windows service via ServiceController. SignalR auto-reconnect plus the existing ConnectionRestoredEvent handle the refresh, so the UI repopulates counters and the active list once the worker is back up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.11" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.11" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||||
|
<PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -255,6 +255,51 @@ public sealed partial class IslandsShellViewModel : ViewModelBase
|
|||||||
await _updateCheck.CheckNowAsync(CancellationToken.None);
|
await _updateCheck.CheckNowAsync(CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ObservableProperty] private string? _restartWorkerStatus;
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task RestartWorkerAsync()
|
||||||
|
{
|
||||||
|
if (!OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
await FlashRestartStatusAsync("Service control is Windows-only.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RestartWorkerStatus = "Restarting worker…";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
using var sc = new System.ServiceProcess.ServiceController("ClaudeDoWorker");
|
||||||
|
if (sc.Status != System.ServiceProcess.ServiceControllerStatus.Stopped)
|
||||||
|
{
|
||||||
|
sc.Stop();
|
||||||
|
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(20));
|
||||||
|
}
|
||||||
|
sc.Start();
|
||||||
|
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running, TimeSpan.FromSeconds(20));
|
||||||
|
});
|
||||||
|
await FlashRestartStatusAsync("Worker restarted.");
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
// ServiceController throws this when the service is not installed.
|
||||||
|
await FlashRestartStatusAsync("ClaudeDoWorker service is not installed.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await FlashRestartStatusAsync($"Restart failed: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task FlashRestartStatusAsync(string text)
|
||||||
|
{
|
||||||
|
RestartWorkerStatus = text;
|
||||||
|
await Task.Delay(3000);
|
||||||
|
if (RestartWorkerStatus == text) RestartWorkerStatus = null;
|
||||||
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void DismissBanner()
|
private void DismissBanner()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -67,6 +67,8 @@
|
|||||||
Foreground="{DynamicResource TextDimBrush}">
|
Foreground="{DynamicResource TextDimBrush}">
|
||||||
<MenuItem Header="Check for updates"
|
<MenuItem Header="Check for updates"
|
||||||
Command="{Binding CheckForUpdatesCommand}"/>
|
Command="{Binding CheckForUpdatesCommand}"/>
|
||||||
|
<MenuItem Header="Restart worker"
|
||||||
|
Command="{Binding RestartWorkerCommand}"/>
|
||||||
<MenuItem Header="About…" Command="{Binding OpenAboutCommand}"/>
|
<MenuItem Header="About…" Command="{Binding OpenAboutCommand}"/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|||||||
Reference in New Issue
Block a user