Powershell foreach относительно нескольких коллекций

Итак, у меня есть сценарий powershell, с которым я играю, и я хотел бы попросить помощи у сообщества. Я должен предварить, что я не всегда лучший в общении с тем, что я пытаюсь сделать, отчасти потому, что у меня нет опыта программирования, поэтому, пожалуйста, терпите меня и задавайте вопросы/поправляйте меня, если я использую неправильные слова, чтобы объяснить, что я имею в виду.

С учетом сказанного, вот что я пытаюсь сделать:

при увеличении как служб, так и типов запуска:

  • остановить службу A ($services) на сервере X ($rebootingServer)

  • #P5# <блочная цитата> #P6#
  • Включить службу A на сервере Y на основе списка текстовых файлов $startuptypes

  • Запустить службу A на сервере Y
  • Промойте и повторяйте, пока $services и $startuptypes не окажутся в конце каждого списка.

Итак, предположим, что $services имеет:
bits appmgmt

и $startuptypes имеет:

Automatic Manual

я хочу, чтобы они применялись соответственно (биты> автоматическое приложение> вручную)

Вот что у меня есть до сих пор:

$services = Get-Content "C:\TEMP\services.txt"
$Startuptypes = Get-Content "C:\TEMP\StartupTypes.txt"
$RebootingServer = Read-Host 'Name of the server that you are bringing down'
$FailoverServer = Read-Host 'Name of the server it is failing over to'


#foreach ($service in $services && $Startuptype in $Startuptypes) {

Invoke-Command -ComputerName $RebootingServer -ArgumentList $service - ScriptBlock {param($service) Stop-Service $service}
Start-Sleep -s 3
Invoke-Command -ComputerName $RebootingServer -ArgumentList $service - ScriptBlock {param($service) set-service $service -StartupType Disabled}
Start-Sleep -s 10
Invoke-Command -ComputerName $FailoverServer -ArgumentList $service $StartupType -ScriptBlock {param($service,$startuptype) Set-Service $service -StartupType $startuptype}
Start-Sleep -s 3
Invoke-Command -ComputerName $FailoverServer -ArgumentList $service - ScriptBlock {param($service) Start-Service $service}
Start-sleep -s 10
}

Оператор «для каждого» - это псевдокод того, что я хочу, чтобы он делал, но не уверен, существует ли он или как его написать соответственно. Я даже не знаю, как это правильно назвать. Несколько условий? Кроме того, как мне правильно написать то, что я пытаюсь выполнить? Спасибо за любую помощь в расширении.


person Sh3perd    schedule 01.11.2018    source источник


Ответы (1)


Похоже, вы хотите перечислить элементы 2 коллекций в соответствующих парах: на итерации 1 обработать элемент 1 из коллекции A вместе с элементом 1 из коллекции B, .. .

Решение PowerShell 6:

# Sample collections.
# Note that their counts must match.
$services     = 'serviceA', 'serviceB', 'serviceC'
$startupTypes = 'automatic', 'manual', 'disabled '


$i = 0 # helper index var.
foreach ($service in $services) { # enumerate $services directly

   # Using the index variable, find the corresponding element from 
   # the 2nd collection, $startupTypes, then increment the index.
   $startupType = $startupTypes[$i++]

   # Now process $service and $startupType as needed.
}

Решение PowerShell 7+:

PowerShell 7 построен на основе .NET Core 3.1, где System.Linq.Enumerable.Zip имеет перегрузку, которая возвращает (2-элементные) кортежи, что упрощает решение:

  • Предостережение: при входных коллекциях разного размера перечисление останавливается, когда в меньшей коллекции заканчиваются элементы.
# Sample collections.
# Note: Due to use of [Linq.Enumerable]::Zip() below:
#  * The element counts need *not* match, because pairing stops 
#    once the shorter collection has run out of elements.
#  * However, note that strongly typed type constraint ([string[]]),
#    which is required for PowerShell to find the right [Linq.Enumerable]::Zip()
#    method overload. You can also *cast* on demand. 
[string[]] $services     = 'serviceA', 'serviceB', 'serviceC'
[string[]] $startupTypes = 'automatic', 'manual', 'disabled '

# Enumerate the collection in pairs (2-element tuples).
# Note that the tuple elements are always named .Item1 and .Item2.
[Linq.Enumerable]::Zip($services, $startupTypes) | ForEach-Object {
  "service: {0}; startup type: {1}" -f $_.Item1, $_.Item2 
}

Как правило, обратите внимание, что в PowerShell версии 7.0 отсутствует поддержка методов расширения .NET (именно поэтому здесь требуется явное использование [System.Linq.Enumerable]), а также отсутствует всесторонняя поддержка вызова универсальных методов, хотя на GitHub есть запросы на добавление функций — см. здесь и здесь.

Вышеизложенное дает:

service: serviceA; startup type: automatic
service: serviceB; startup type: manual
service: serviceC; startup type: disabled 
person mklement0    schedule 01.11.2018