Restart-Service не имеет параметра -ComputerName
для управления службами на удаленных машинах. Чтобы использовать этот командлет удаленно, вы можете использовать
Invoke-Command -Computername $computer -ArgumentList $ServiceName -ScriptBlock {
param($service)
Restart-Service -Name $service}
Edit
Lee_Daily , указав, что объект возвращениз Get-Service
содержит свойство MachineName
. Когда этот объект используется в следующем Restart-Service
в качестве параметра InputObject
, командлет использует это свойство MachineName для перезапуска службы на этом удаленном компьютере.
Поскольку я никогда не думал об этом, я былтестирование с ним, и оно действительно работает таким образом.
Ваш код (с исправленным параметром ComputerName) должен работать должным образом, при условии, что у вас есть права на удаленных компьютерах:
$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"
}
}
Это, однако, не позволяет добавлять учетные данные пользователя, поскольку Get-Service
не предоставляет объект Credentials
. Если вам нужно использовать разные учетные данные, вы можете сделать следующее:
$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"
}
}
Последний вариант, который я могу придумать, - это использовать командлет Get-WmiObject
, который для удобства я обернул в пользовательскую функцию:
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()
}
Ваш код может выглядеть следующим образом:
$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
}