28

I came across this one liner that appears to work:

stop-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)

Can anyone explain why, because I thought stop-service didn't work unless you either used remoting or it occurred on the local host.

fenster
  • 1,809
  • 6
  • 22
  • 24

9 Answers9

47

The output of Get-Service is a System.ServiceProcess.ServiceController .NET class that can operate on remote computers. How it accomplishes that, I don't know - probably DCOM or WMI. Once you've gotten one of these from Get-Service, it can be passed into Stop-Service which most likely just calls the Stop() method on this object. That stops the service on the remote machine. In fact, you could probably do this as well:

(get-service -ComputerName remotePC -Name Spooler).Stop()
Keith Hill
  • 194,368
  • 42
  • 353
  • 369
  • 7
    Note: Tested this method, and it does make the call to the remote host, but does not wait for the Service to stop before continuing the script. If you do a Stop() and Start(), the Start() will likely fail because the Service isn't stopped yet. Just FYI if you want to do more then Stop in your script (which is beyond what this question asked) – Jason Coon Mar 05 '13 at 20:10
  • Just a powershell question I think: Is it possible to do this from a batch file like putting multiple of those lines for multiple machines after each other (like .bat) – Hace Nov 22 '13 at 11:06
  • 1
    In newer versions (3+?) of Powershell you can get the service and then use its [`.WaitForStatus` method](http://www.powershellmagazine.com/2013/04/10/pstip-wait-for-a-service-to-reach-a-specified-status/) – Baodad Nov 19 '14 at 17:45
  • @Hace if ur doing it from batch.. why not just use 'sc stop ' ? – Luigi Sep 01 '15 at 13:44
6

Thanks to everyone's contributions to this question, I've come up with the following script. Change the values for $SvcName and $SvrName to suit your needs. This script will start the remote service if it is stopped, or stop it if it is started. And it uses the cool .WaitForStatus method to wait while the service responds.

#Change this values to suit your needs:
$SvcName = 'Spooler'
$SvrName = 'remotePC'

#Initialize variables:
[string]$WaitForIt = ""
[string]$Verb = ""
[string]$Result = "FAILED"
$svc = (get-service -computername $SvrName -name $SvcName)
Write-host "$SvcName on $SvrName is $($svc.status)"
Switch ($svc.status) {
    'Stopped' {
        Write-host "Starting $SvcName..."
        $Verb = "start"
        $WaitForIt = 'Running'
        $svc.Start()}
    'Running' {
        Write-host "Stopping $SvcName..."
        $Verb = "stop"
        $WaitForIt = 'Stopped'
        $svc.Stop()}
    Default {
        Write-host "$SvcName is $($svc.status).  Taking no action."}
}
if ($WaitForIt -ne "") {
    Try {  # For some reason, we cannot use -ErrorAction after the next statement:
        $svc.WaitForStatus($WaitForIt,'00:02:00')
    } Catch {
        Write-host "After waiting for 2 minutes, $SvcName failed to $Verb."
    }
    $svc = (get-service -computername $SvrName -name $SvcName)
    if ($svc.status -eq $WaitForIt) {$Result = 'SUCCESS'}
    Write-host "$Result`: $SvcName on $SvrName is $($svc.status)"
}

Of course, the account you run this under will need the proper privileges to access the remote computer and start and stop services. And when executing this against older remote machines, you might first have to install WinRM 3.0 on the older machine.

Baodad
  • 2,405
  • 2
  • 38
  • 39
4

Based on the built-in Powershell examples, this is what Microsoft suggests. Tested and verified:

To stop:

(Get-WmiObject Win32_Service -filter "name='IPEventWatcher'" -ComputerName Server01).StopService()

To start:

(Get-WmiObject Win32_Service -filter "name='IPEventWatcher'" -ComputerName Server01).StartService()
Eric
  • 4,201
  • 5
  • 27
  • 36
Sam Murcio
  • 171
  • 2
2

This worked for me, but I used it as start. powershell outputs, waiting for service to finshing starting a few times then finishes and then a get-service on the remote server shows the service started.

**start**-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)
kleopatra
  • 51,061
  • 28
  • 99
  • 211
timassin
  • 21
  • 1
2

Another option; use invoke-command:

cls
$cred = Get-Credential
$server = 'MyRemoteComputer'
$service = 'My Service Name' 

invoke-command -Credential $cred -ComputerName $server -ScriptBlock {
    param(
       [Parameter(Mandatory=$True,Position=0)]
       [string]$service
    )
    stop-service $service 
} -ArgumentList $service

NB: to use this option you'll need PowerShell to be installed on the remote machine and for the firewall to allow requests through, and for the Windows Remote Management service to be running on the target machine. You can configure the firewall by running the following script directly on the target machine (one off task): Enable-PSRemoting -force.

JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
0

You can also do (Get-Service -Name "what ever" - ComputerName RemoteHost).Status = "Stopped"

  • 2
    hmm forget that. If do get-service again, it is still at the same status. I was assigning this to a variable and, thus, assigning the status attribut works, but it does not actually stop the service on the remote host. Sorry – Stéphane Lacasse Nov 13 '12 at 01:44
  • 1
    It's a read-only property: http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicecontroller.status.aspx. – dartonw May 03 '13 at 04:04
  • @StéphaneLacasse, I also assigned it to a variable `$s = (Get-Service -Computername RemoteHost -Name MyService)` and then just executed `$s.Stop()`. Then I did `Write-host $($s.Status)` and the service was still running, but if I waited for 10 seconds for the service to stop, and then did `$s=(Get-Service ...` and `Write-host $($s.Status)` again, it came back with a status of 'Stopped' – Baodad Jul 09 '14 at 04:31
0

You could just run a foreach and have logging enabled. The console will show if something goes wrong and you can look in the log.

That way, you can then handle the errors individually.

I think it works better this way than running a Test-Netconnection for the verification part because firewall rules can create the value false.

For this example you ned a csv file with column ServerName, Populate the column with servername.contoso.com

$ServerList = "$PSScriptRoot\Serverlist.csv"

$Transcriptlog = "$PSScriptRoot\Transcipt.txt"
    
    Start-Transcript -Path $Transcriptlog -Force
    Get-Date -Format "yyyy/MM/dd HH:mm" 
    
    Try 
     { # Start Try  
       $ImportServerList = Import-Csv $ServerList -Encoding UTF8 | ForEach-Object { # Start Foreach 
        New-Object PsObject -Prop @{ # Start New-Object 
         ServerName = $_.ServerName } # End NewObject 
          Invoke-Command -ComputerName $_.ServerName -ErrorAction Continue -ScriptBlock  { # Start ScriptBlock  
           # Disable Service PrintSpooler
           Get-Service -Name Spooler | Stop-Service -Force 
    
       } # End ScriptBlock
      } # End Foreach       
     } # End Try
    
    Catch
     { # Start Catch 
      Write-Warning -Message "## ERROR## " 
      Write-Warning -Message "## Script could not start ## " 
      Write-Warning $Error[0]
     } # End Catch
    
    Stop-Transcript
Fardin Barashi
  • 54
  • 3
  • 11
-2

stop-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)

This fails because of your variables -ComputerName remotePC needs to be a variable $remotePC or a string "remotePC" -Name Spooler(same thing for spooler)

Joel
  • 7,401
  • 4
  • 52
  • 58
PhilB
  • 1
-6

As far as I know, and I cant verify it now, you cannot stop remote services with the Stop-Service cmdlet or with .Net, it is not supported.

Yes it works, but it stopes the service on your local machine, not on the remote computer.

Now, if the above is correct, without remoting or wmi enabled, you could set a scheduled job on the remote system, using AT, that runs Stop-Service locally.

Shay Levy
  • 121,444
  • 32
  • 184
  • 206
  • 1
    I have verified that it does work and doesn't stop the service on the local machine. I'm surprised it is not more widely known/used. – fenster Apr 27 '12 at 16:32