Question:
In powershell, I’ve seen multiple ways to stop a service
The more modern way
1 2 |
Stop-Service wuauserv |
And the more legacy way
1 2 |
NET STOP WUAUSERV |
The legacy way is much more difficult to automate because it is not natively idempotent.
I have powershell scripts that builds a windows golden images using packer. Initially the scripts used NET STOP
. I found once I switched to Stop-Service
, I seemed to get more frequent failures when rebooting a VM after installing windows updates.
Do both Stop-Service
and NET STOP
produce the same result? Or are there differences between them that might explain why the legacy one seems more reliable?
Answer:
For a Windows service that is:
- currently running
- and stoppable in principle
both net stop
and Stop-Service
should act the same, namely synchronously:
That is, they send the specified service a stop request and wait for stopping to complete (net stop
invariably waits, while, in PSv5+, you can opt out of waiting with Stop-Service
‘s -NoWait
switch).
Unlike net stop
(which reports an error if the service is already stopped), Stop-Service
is idempotent (exhibits desired-state logic): If the target service is already in the stopped state, the command is a quiet no-op.
(As an aside: Start-Service
is also synchronous, but invariably so, and is also idempotent.)
Set-Service -Status Stopped
should act the same as Stop-Service
, except that:
- unlike
Stop-Service
, it doesn’t support-Force
in order to stop a service with running dependents (other services that depend on the service being stopped). - due to what I presume to be a bug you cannot even stop services that themselves depend on other services(!).
- in effect, as of Windows PowerShell v5.1 / PowerShell Core v6.0-rc, you can only stop services with
Set-Service -Status Stopped
that have no dependents (no services that depend on them), nor themselves depend on other services.
Optional reading: looking at the Stop-Service
and Start-Service
source code:
The publicly available source code on GitHub is for the cross-platform Core edition of PowerShell, but it looks like the code in question was essentially taken unmodified from the Windows PowerShell version.
Stop-Service
: The part where the code waits for the service to be in theServiceControllerStatus.Stopped
state[1]
, which is only bypassed if the-NoWait
switch is explicitly specified, in which case variablewaitForServiceToStop
is set tofalse
.Start-Service
: The part where the code invariably waits for the service to be in theServiceControllerStatus.Running
state.
[1] If reaching the target state takes longer than 2 seconds, the waiting loop issues a warning (every 2 seconds) while continuing to wait; waiting is only aborted with an error if the service is unexpectedly neither in the target-state-pending state nor in the target state.