使用PowerShell运行命令

使用PowerShell运行命令,powershell,cmd,command,Powershell,Cmd,Command,我想制作一个脚本,如果我在我的机器上打开它(作为管理员),它将在不同的机器上运行命令(不输入凭据)。 我曾经制作一个脚本来重新启动服务。我是这样做的: $out = "lokation\output_NoService.txt" Clear-Content $out $data = Get-Content "lokation\input_PCs.txt" foreach ($line in $data) { $computer = $line.Split(":")[0] $S

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

$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"
    }
}
$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
}
input_PCs.txt
包含机器名和要重新启动的服务的名称。 例如:
PCName:Servicename

这就是我想从txt扫描PC并在txt格式的机器上运行命令的方式

例如,这样的命令

从c驱动器运行example.exe+参数。 因此:
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驱动器。

类似的内容

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驱动器。

没有用于管理远程计算机上的服务的
-ComputerName
参数。要远程使用该cmdlet,可以使用

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

编辑


指出从
Get Service
返回的对象包含
MachineName
属性。当此对象作为
InputObject
参数在以下
Restart Service
中使用时,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 = $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"
    }
}
$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
}
没有用于管理远程计算机上的服务的
-ComputerName
参数。要远程使用该cmdlet,可以使用

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

编辑


指出从
Get Service
返回的对象包含
MachineName
属性。当此对象作为
InputObject
参数在以下
Restart Service
中使用时,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 = $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"
    }
}
$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
中的第二个连字符前添加一个空格。对我来说,它看起来应该可以正常工作。。。你有什么问题?除了其他事情,您需要在>>
Get Service COmputerName
中的第二个连字符前面添加一个空格,我认为上一个
Get Service
调用中的对象将具有
.MachineName
属性,这意味着
-InputObject
参数将使用该属性联系远程系统。我无法测试[只有一个系统],但我记得在有关该主题的帖子中,当对远程系统使用时,
Get Service
管道连接到
Restart Service
。@Lee_Dailey有趣!我必须承认我从来没有想过。。我现在在手机上,所以无法测试。我期待着看到你的结果。。。[grin]@Lee_Dailey需要做一些工作来测试这一点,但您是对的,
MachineName
属性由
重新启动服务
cmdlet使用,前提是
获取服务
返回的对象是通过参数
-InputObject
提供的。在处理这个问题的同时,我还添加了一个使用
getwmiobject
的方法。谢谢尼托![grin]如果您想了解完整性,还可以使用
调用命令
,或
新建PSSession
输入PSSession
。。。但这就是编写完整教程的过程……我认为上一个
Get Service
调用中的对象将具有
.MachineName
属性,这意味着
-InputObject
参数将使用该属性联系远程系统。我无法测试[只有一个系统],但我记得在有关该主题的帖子中,当对远程系统使用时,
Get Service
管道连接到
Restart Service
。@Lee_Dailey有趣!我必须承认我从来没有想过。。我现在在手机上,所以无法测试。我期待着看到你的结果。。。[grin]@Lee_Dailey需要做一些工作来测试这一点,但您是对的,
MachineName
属性由
Restart-Service
cmdlet使用,前提是
Get-Service
返回的对象是通过参数
-InputOb提供的