Почему время выполнения «invoke-command» так отличается в этих двух сценариях PowerShell

#powershell #invoke-command

#powershell #invoke-command

Вопрос:

Мне нужно получить некоторую информацию от клиентов с помощью «invoke-command», и я начал писать сценарий для запроса компьютеров из AD, помещать их в переменную, использовать переменную для проверки того, какие компьютеры подключены к сети или оффлайн, помещать статус в хеш-таблицу, а затем запускать invoke-command только на компьютерах в Сети. Работая над этим, я подумал, что было бы проще не использовать хэш-таблицу, вместо этого выполнить foreach test-connection непосредственно перед выполнением invoke-command. Итак, я клонировал и переписал. Теперь оба сценария завершены, и мне интересно, почему «invoke-command» выполняется намного медленнее после цикла «ForEach Test-connection», тогда как в моем другом сценарии это только половина времени. Кроме того, параметр -ErrorVariable также не работает. Вот что я имею в виду:

 Measure-Command {
#########################################################################################
# Check Computerstatus and put into hashtable
#########################################################################################
$computerstatus = @{}
ForEach ($computer in $adcomputers) {
  $result = Test-Connection $computer -Count 1 -quiet
     If ($result) {$computerstatus.add( $computer, 'online')}
          else {$computerstatus.add( $computer, 'offline')}
 }
# Read hashtable and set Online/Offline variable:
$computersonline = Foreach ($Key in ($computerstatus.GetEnumerator() | Where-Object {$_.Value -eq "online"})) {$Key.name}
$computersoffline = Foreach ($Key in ($computerstatus.GetEnumerator() | Where-Object {$_.Value -eq "offline"})) {$Key.name}

#########################################################################################
# Now run the invoke-command on online computers
#########################################################################################
$remotequery = Invoke-command -ComputerName $computersonline -ErrorAction SilentlyContinue -ErrorVariable MyErrorVar4InvCmd -scriptblock {remote-command}  | select Property | where Property -match 'True'
$cantaccess = $MyErrorVar4InvCmd.TargetObject

} # end measure-command
  

Общее количество секунд: 34 9779497 и » $ cantaccess = $ MyErrorVar4InvCmd.targetObject» отображается правильно

И другой, медленный, подход:

 Measure-Command {
#########################################################################################
# Now run the invoke-command
#########################################################################################
$queryresult = @()     # create blank array, it will get filled with  =
$CompOFFLINE = @()
ForEach ($computer in $adcomputers) {
  if (Test-Connection $computer -Count 1 -quiet) {
       $remotequery = Invoke-command -ComputerName $computer -ErrorAction SilentlyContinue -ErrorVariable MyErrorVar4InvCmd -scriptblock {remote-command} | select Property | where Property -match 'True'
        if ($remotequery.Property -eq 'true') {
           $queryresult  = $computer
        }
        else {
               }
  }
    else {
    $CompOFFLINE  = $computer
    }
}

$cantaccess = $MyErrorVar4InvCmd.TargetObject

} # end measure-command
  

Общее количество секунд: 107 4585155 и «$ cantaccess = $ MyErrorVar4InvCmd.targetObject» пусто…

Спасибо, Роберт

Комментарии:

1. 2-й выполняется медленно, потому что вы используете = в массиве. это создает НОВЫЙ массив каждый раз, когда вы добавляете к нему… массивы имеют фиксированный размер , поэтому для добавления к одному требуется создание нового, большего размера.

2. вы можете значительно ускорить процесс, используя -Computer параметр Invoke-Command … он принимает набор имен компьютеров и scriptblock для запуска в этих системах… параллельно .

3. спасибо за объяснение. что касается предложения по скорости: я уже работаю с массивом компьютеров (в $ adcomputers) 😉

4. добро пожаловать! [ усмешка ] ///// ваш ForEach ($computer in $adcomputers) не выполняет ничего параллельно . он запускает их по одному за раз — и он запускает их локально. если вы используете Invoke-Command и передаете ему список систем в виде списка вы будете запускать блоки сценариев параллельно и в целевых системах . это значительно ускорит работу, если у вас есть значительное количество систем для работы. [ усмешка ]

5. теперь я понимаю, что вы имеете в виду. Спасибо 🙂