Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Whats the difference between powershell's Stop-Service and NET-STOP

Tags:

powershell

In powershell, I've seen multiple ways to stop a service

The more modern way

Stop-Service wuauserv

And the more legacy way

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?

like image 224
spuder Avatar asked Jan 04 '23 04:01

spuder


2 Answers

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 the ServiceControllerStatus.Stopped state[1] , which is only bypassed if the -NoWait switch is explicitly specified, in which case variable waitForServiceToStop is set to false.

  • Start-Service: The part where the code invariably waits for the service to be in the ServiceControllerStatus.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.

like image 58
mklement0 Avatar answered Jan 14 '23 14:01

mklement0


The difference is waiting until the service is actually stopped. net stop service waits until service gets stopped, or at least sends the event that it's now "stopped". The "other legacy" way of sc stop service exits at once after sending stop signal, and dumps current service state which is normally STOP_PENDING. Stop-Service cmdlet does wait for service to stop, but there might be corner cases with services that are stopping for too long and the cmdlet bails off, or it had a -nowait switch in there. Also some services are restarted if needed, so a further check might be required, like this (in case a service didn't stop):

Stop-Service $servicename
$sleep=0
$s="Running"
do {
   $sleep++
   start-sleep 1
   $s=(get-service $servicename).status
} while (($s -ne "Stopped") -and ($sleep -le 20))
like image 27
Vesper Avatar answered Jan 14 '23 15:01

Vesper