Запустить команду с PowerShell - PullRequest
0 голосов
/ 07 октября 2019

Я хочу создать скрипт, который, если я открою его на своей машине (как администратор), будет запускать команду на разных машинах (без ввода учетных данных). Я использовал, чтобы сделать скрипт, который перезапускает сервисы. Я сделал это так:

$out = "lokation\output_NoService.txt"
Clear-Content $out

$data = Get-Content "lokation\input_PCs.txt"

foreach ($line in $data) {
    $computer = $line.Split(":")[0]
    $ServiceName = $line.Split(":")[1]

    if ($sObj = Get-Service-COmputerName $Computer -Name $ServiceName -ErrorAction SilentlyContinue) {
        Restart-Service -InputObj $sObj
        Write-Host "Restarting $ServiceName on $computer"
    } else {
        Write-Host "$ServiceName is not running on $computer"
        Add-Content $out "$computer;$ServiceName"
    }
}

input_PCs.txt содержит имена компьютеров и имя службы, которая будет перезапущена. Например: PCName:Servicename

Вот как я хочу сканировать ПК из txt и запускать команды на машинах, которые находятся в txt.

Например, такая команда.

запустить example.exe + параметры с диска c. Ergo: C:\example.exe -paramaters

Ответы [ 2 ]

2 голосов
/ 07 октября 2019

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
}
0 голосов
/ 07 октября 2019

Как-то так?

foreach($line in $data) {

    $computer = $line.split(":")[0]   

    Invoke-Command -ComputerName $computer -ScriptBlock {C:\example.exe -parameters}

}

Чтобы это работало, example.exe должен присутствовать на ваших удаленных компьютерах. Если это еще не так, до этого вы можете добавить что-то вроде

if (!(Test-Path -Path "\\$computer\c$\example.exe")) {

    Copy-Item -Path "X:\path_to_file\example.exe" -Destination "\\$computer\c$" -Force

}

И если вы не хотите, чтобы он запрашивал какие-либо учетные данные, убедитесь, что ваш сеанс Powershell запущен под вашимпользователь с правами администратора, имеющий доступ ко всем c-дискам компьютеров.

...