运行 使用 PowerShell 命令

Run command with PowerShell

我想制作一个脚本,如果我在我的机器上打开它(作为管理员),它 运行 是不同机器上的命令(无需输入凭据)。 我曾经制作一个重启服务的脚本。我是这样做的:

$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 格式的计算机上扫描 PC 的方式。

比如这样的命令。

运行 example.exe + c 盘的参数。 因此:C:\example.exe -paramaters

是这样的吗?

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 驱动器的管理员用户下启动的。

Restart-Service 没有 -ComputerName 参数来管理远程机器上的服务。要远程使用该 cmdlet,您可以使用

Invoke-Command -Computername $computer -ArgumentList $ServiceName -ScriptBlock { 
    param($service)
    Restart-Service -Name $service}


编辑


Lee_Daily指出从Get-Service返回的对象包含一个MachineName属性。当此对象在以下 Restart-Service 中用作 InputObject 参数时,cmdlet 使用该 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 cmdlet,为方便起见,我将其包装在自定义函数中:

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
}