The Restart-Service does not have a -ComputerName parameter to manage services on remote machines. To use that cmdlet remotely, you can use
Invoke-Command -Computername $computer -ArgumentList $ServiceName -ScriptBlock {
param($service)
Restart-Service -Name $service}
Edit
Lee_Daily pointed out that the object returned from Get-Service contains a MachineName property. When this object is used in a following Restart-Service as InputObject parameter, the cmdlet uses that MachineName property to restart the service on that remote machine.
As I have never thought of that, I've been testing with it and indeed it does work that way.
Your code (with corrected ComputerName parameter) should therefore work as intended, provided you have permissions on the remote computers to do so:
$out = "lokation\output_NoService.txt"
Clear-Content $out
$data = Get-Content "lokation\input_PCs.txt"
foreach ($line in $data) {
$computer, $serviceName = $line -split ':', 2
if ($sObj = Get-Service -ComputerName $computer -Name $serviceName -ErrorAction SilentlyContinue) {
Restart-Service -InputObj $sObj
Write-Host "Restarting $serviceName on $computer"
}
else {
Write-Host "Service '$serviceName' cannot be found on computer '$computer'"
Add-Content -Path $out -Value "$computer; $serviceName"
}
}
This however does not let you add user credentials because Get-Service does not provide a Credentials object.
If you need to use different credentials, you can do like below:
$credential = Get-Credential
$out = "lokation\output_NoService.txt"
Clear-Content $out
$data = Get-Content "lokation\input_PCs.txt"
# unravel the $credential object into plain username and password:
$user = $credential.GetNetworkCredential().UserName
$password = $credential.GetNetworkCredential().Password
foreach ($line in $data) {
$computer, $serviceName = $line -split ':', 2
# create a connection to the remote machine using credentials
net use "\\$computer\c$" $password /USER:$user
if ($sObj = Get-Service -ComputerName $computer -Name $serviceName -ErrorAction SilentlyContinue) {
Restart-Service -InputObj $sObj
Write-Host "Restarting $serviceName on $computer"
}
else {
Write-Host "Service '$serviceName' cannot be found on computer '$computer'"
Add-Content -Path $out -Value "$computer; $serviceName"
}
}
The last option I can think of is to use the Get-WmiObject cmdlet which for convenience I've wrapped in a custom function:
function Restart-RemoteService {
[CmdletBinding()]
Param(
[Parameter(Position = 0,Mandatory = $true, ValueFromPipelineByPropertyName = $true,ValueFromPipeline = $true)]
[string]$ComputerName,
[Parameter(Position = 1,Mandatory = $true)]
[string]$ServiceName,
[Parameter(Position = 2,Mandatory = $true)]
[string]$ErrorFile
[Parameter(Mandatory = $false)]
[System.Management.Automation.PSCredential]$Credential
)
$wmiParams = @{
'Class' = 'Win32_Service'
'ComputerName' = $ComputerName
'Filter' = "Name='$ServiceName'"
}
if ($Credential) { $wmiParams['Credential'] = $Credential }
$svc = Get-WmiObject @wmiParams
if (!$svc) {
Write-Warning "Service '$ServiceName' cannot be found on computer '$ComputerName'"
Add-Content -Path "lokation\output_NoService.txt" -Value "$ComputerName; $ServiceName"
}
if ($svc.State -eq 'Running') {
Write-Verbose "Stopping service '$ServiceName' on computer '$ComputerName'"
[void]$svc.StopService()
$maxWait = 20
do {
Start-Sleep -Milliseconds 100
$maxWait--
if ($maxWait -le 0) {
Throw "Could not stop service '$ServiceName'"
}
} while (( Get-WmiObject @wmiParams).State -ne 'Stopped')
}
Write-Verbose "Starting service '$ServiceName' on computer '$ComputerName'"
[void]$svc.StartService()
}
Your code could then look like this:
$out = "lokation\output_NoService.txt"
Clear-Content $out
$data = Get-Content "lokation\input_PCs.txt"
foreach ($line in $data) {
$computer, $serviceName = $line -split ':', 2
# if needed, you can pass Credentials too
Restart-RemoteService -ComputerName $computer -ServiceName $serviceName -ErrorFile $out -Verbose
}
Get-Service-COmputerName<<<