diff --git a/initsystem/winscm.go b/initsystem/winscm.go index 323efca8..93fb4678 100644 --- a/initsystem/winscm.go +++ b/initsystem/winscm.go @@ -20,16 +20,28 @@ type WinSCM struct{} func (WinSCM) String() string { return "winscm" } // StartService starts a service. +// +// -WarningAction SilentlyContinue suppresses the benign "Waiting for service +// '…' to start..." progress warning that Start-Service emits when a service +// stays in StartPending for a moment (common on a cold first start). That +// warning goes to the warning stream, which lands on stderr under a subprocess, +// and rig treats any Windows stderr output as a failure. -ErrorAction Stop +// still turns a genuine start failure into a terminating (non-zero) error, so +// real failures are still detected. func (c WinSCM) StartService(ctx context.Context, h cmd.ContextRunner, s string) error { - if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nStart-Service "+ps.SingleQuote(s)+" -ErrorAction Stop", cmd.PS()); err != nil { + if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nStart-Service "+ps.SingleQuote(s)+" -ErrorAction Stop -WarningAction SilentlyContinue", cmd.PS()); err != nil { return fmt.Errorf("failed to start service %s: %w", s, err) } return nil } // StopService stops a service. +// +// -WarningAction SilentlyContinue suppresses the benign "Waiting for service +// '…' to stop..." progress warning (StopPending) for the same reason as +// StartService; -ErrorAction Stop still surfaces genuine failures. func (c WinSCM) StopService(ctx context.Context, h cmd.ContextRunner, s string) error { - if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nStop-Service "+ps.SingleQuote(s)+" -ErrorAction Stop", cmd.PS()); err != nil { + if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nStop-Service "+ps.SingleQuote(s)+" -ErrorAction Stop -WarningAction SilentlyContinue", cmd.PS()); err != nil { return fmt.Errorf("failed to stop service %s: %w", s, err) } return nil @@ -41,8 +53,12 @@ func (c WinSCM) ServiceScriptPath(_ context.Context, _ cmd.ContextRunner, _ stri } // RestartService restarts a service. +// +// -WarningAction SilentlyContinue suppresses the benign "Waiting for service +// '…' to start/stop..." progress warnings for the same reason as StartService; +// -ErrorAction Stop still surfaces genuine failures. func (c WinSCM) RestartService(ctx context.Context, h cmd.ContextRunner, s string) error { - if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nRestart-Service "+ps.SingleQuote(s)+" -ErrorAction Stop", cmd.PS()); err != nil { + if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nRestart-Service "+ps.SingleQuote(s)+" -ErrorAction Stop -WarningAction SilentlyContinue", cmd.PS()); err != nil { return fmt.Errorf("failed to restart service %s: %w", s, err) } return nil diff --git a/initsystem/winscm_test.go b/initsystem/winscm_test.go index 3d528dce..1098a275 100644 --- a/initsystem/winscm_test.go +++ b/initsystem/winscm_test.go @@ -45,6 +45,9 @@ func TestWinSCMStartService(t *testing.T) { script := decodePSCmd(t, mr.LastCommand()) require.Contains(t, script, "Start-Service") require.Contains(t, script, "-ErrorAction Stop") + // Suppresses the benign StartPending progress warning that otherwise + // lands on stderr and trips ErrWroteStderr on a slow/cold start. + require.Contains(t, script, "-WarningAction SilentlyContinue") require.Contains(t, script, "'myservice'") }) t.Run("failure", func(t *testing.T) { @@ -63,6 +66,8 @@ func TestWinSCMStopService(t *testing.T) { script := decodePSCmd(t, mr.LastCommand()) require.Contains(t, script, "Stop-Service") require.Contains(t, script, "-ErrorAction Stop") + // Suppresses the benign StopPending progress warning (see StartService). + require.Contains(t, script, "-WarningAction SilentlyContinue") require.Contains(t, script, "'myservice'") }) t.Run("failure", func(t *testing.T) { @@ -81,6 +86,8 @@ func TestWinSCMRestartService(t *testing.T) { script := decodePSCmd(t, mr.LastCommand()) require.Contains(t, script, "Restart-Service") require.Contains(t, script, "-ErrorAction Stop") + // Suppresses the benign start/stop progress warnings (see StartService). + require.Contains(t, script, "-WarningAction SilentlyContinue") require.Contains(t, script, "'myservice'") }) t.Run("failure", func(t *testing.T) {