Назад | Перейти на главную страницу

Принять значение из конвейерной функции Powershell

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

function Test-PSRemoting
{
   Param(
   [Parameter(Mandatory=$True, ValueFromPipeline=$True)] 
   [string[]] $ComputerName,

   [string] $Credential)

   $file = Read-Host "Enter file location for all error details: "

   try {
    $result = Invoke-Command -ComputerName $ComputerName -Credential $Credential { 1 } -ErrorAction SilentlyContinue -ErrorVariable Problem 
    If ($Problem){
    $result = 0}
   } catch {
    $result = 0}

   If ($result -eq 1){
   write-host "PSRemoting is enabled on: " $ComputerName
   } else {
   write-host "PSRemoting is not enabled/working on: " $ComputerName    
   $Problem | Out-File $file -Append}

} 

Функция отлично работает, если я укажу только один компьютер:

Test-PSRemoting -ComputerName Server1 - Credentials Admin

Однако я не могу заставить эту функцию работать, если укажу несколько компьютеров:

Test-PSRemoting -ComputerName Server1, Server2 - Credentials Admin
Server1, Server2 | Test-PSRemoting -Credentials Admin

В этом случае я бы использовал блок Process {} (также отвечает на ваш комментарий о том, почему он проверял только Server2).

function test-ps
{
    param(
     [Parameter(ValueFromPipeline=$true)]
     [string[]] $CN
    )
    process{
        Write-Host $CN "h"
    }
}

'test1','test2' | test-ps

http://ss64.com/ps/syntax-function-input.html

Попробуйте сделать следующее, в комментариях ниже отмечены ключевые моменты.

function Test-PSRemoting
{

[CmdletBinding()]
param
    (
        [Parameter(Mandatory = $True, ValueFromPipeline = $True)] 
        [string[]]$ComputerName,

        [Parameter(Mandatory = $False)]
        [System.Management.Automation.PSCredential]$Credential = (Get-Credential),

        [Parameter(Mandatory = $True)]
        [String]$OutFile
    )

process
    {
        # Pass computer name along the pipeline to allow for more then one.
        $ComputerName | % `
        {
            $pcName = $_;

            $problem = $Null;

            try
            {
                $result = Invoke-Command -ComputerName $pcName -Credential $Credential { 1 } -ErrorAction SilentlyContinue -ErrorVariable problem;

                if ($problem -eq $Null -and $result -eq 1)
                {
                    # Use Write-Verbose instead. Test-* commands are meant to return true/false.
                    # But additional status can be viewed by adding the -Verbose parameter to Test-PSRemoting. i.e. Test-PSRemoting -Verbose
                    Write-Verbose "PSRemoting is enabled on: $pcName";

                    return $True;
                }
                else
                {
                    Write-Verbose "PSRemoting is not enabled/working on: $pcName";

                    $problem | Out-File $OutFile -Append;

                    return $False;
                }
            }
            catch
            {
                return $False
            }
        }
    }
}

Ключевые моменты:

  • Использование $ComputerName | чтобы позволить Test-PSRemoting -ComputerName Server1,Server2 использование, обрабатывая условную логику на указанное имя компьютера. Invoke-Command естественно обрабатывает несколько имен компьютеров, но ваш if заявлений нет.
  • Перемещен $file к $OutFile параметр вместо Read-Host и помечен как обязательный параметр для принудительного ввода. Уходя Read-Host в process { } блок будет означать, что путь к файлу запрашивается несколько раз, если Server1,Server2 | Test-PSRemoting используется. Также имеет то преимущество, что его можно передавать как параметр вместо того, чтобы каждый раз вводить вручную.
  • Подробный вывод перемещен в Write-Verbose вместо того Write-Host. Команды Test- * должны возвращать True / False вместо строки. Использовать -Verbose чтобы увидеть подробный вывод. Кроме того, вы можете изменить Write-Verbose "PSRemoting is not enabled/working on: $pcName"; линия к Write-Warning вместо.