Description
Start, Stop, and Restart service methods follow the exact same boilerplate pattern in both WPF projects:
Servy.Manager/Services/ServiceCommands.cs (lines 95–277, ~165 lines across 3 methods):
Each does: null guard → acquire lock → get domain → check disabled → Task.Run operation → set result → release lock → show message
Servy/Services/ServiceCommands.cs (lines 357–455, ~120 lines across 3+1 methods):
Each does: validate name → check installed → check disabled → call manager → show result → catch unauthorized → catch general
Only the core operation call and message text differ between Start/Stop/Restart.
Estimated redundant lines: ~285
Suggested fix
Extract a generic ExecuteServiceCommandAsync(service, operation, successStatus, successMessage) helper in each project. The Manager project already has ExecuteBulkOperationAsync which demonstrates this pattern.
Description
Start, Stop, and Restart service methods follow the exact same boilerplate pattern in both WPF projects:
Servy.Manager/Services/ServiceCommands.cs (lines 95–277, ~165 lines across 3 methods):
Each does: null guard → acquire lock → get domain → check disabled → Task.Run operation → set result → release lock → show message
Servy/Services/ServiceCommands.cs (lines 357–455, ~120 lines across 3+1 methods):
Each does: validate name → check installed → check disabled → call manager → show result → catch unauthorized → catch general
Only the core operation call and message text differ between Start/Stop/Restart.
Estimated redundant lines: ~285
Suggested fix
Extract a generic
ExecuteServiceCommandAsync(service, operation, successStatus, successMessage)helper in each project. The Manager project already hasExecuteBulkOperationAsyncwhich demonstrates this pattern.