Powershell foreach regarding multiple collections

Sh3perd

So i have a powershell script im toying with that i'd like to ask the community's help. I have to preface that I am not always the best in communicating what I am attempting to do, partly because i dont have programming experience so please bear with me, and ask questions/correct me if i use incorrect words to explain what i mean.

With that said, Here's what I am trying to do:

while incrementing both services and startuptypes:

  • stop service A ($services) on server X ($rebootingServer)

  • Disable service A ($services) on server X ($rebootingServer)

    Given: we know service A is disabled on server Y prior to script running

  • Enable service A on server Y based on text file list $startuptypes

  • Start service A on server Y
  • Rinse and repeat until $services and $startuptypes are at the end of each list

So assume $services has:
bits appmgmt

and $startuptypes has:

Automatic Manual

i want them to be applied respectively (bits > automatic appmgmt > manual)

Heres what i have thus far:

$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
}

The 'for each' statement is pseudo-code of what i want it to do, yet unsure if that exists or how to write it accordingly. I dont even know what that would be appropriately called. Multiple conditionals? That aside, how would i properly write what I am attempting to accomplish? Thank you for any help in advanced.

mklement0

It sounds like you want to enumerate the elements of 2 collections in corresponding pairs: in iteration 1, process element 1 from collection A along with element 1 from collection B, ...

PowerShell 6- solution:

# 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+ solution:

PowerShell 7 is built on .NET Core 3.1, where the System.Linq.Enumerable.Zip has an overload that returns (2-element) tuples, which simplifies the solution:

# 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 
}

Generally, note that PowerShell, as of 7.0, lacks support for .NET extension methods (which is why explicit use of [System.Linq.Enumerable] is required here) and also lacks comprehensive support for calling generic methods, though there are feature requests on GitHub - see here and here.

The above yields:

service: serviceA; startup type: automatic
service: serviceB; startup type: manual
service: serviceC; startup type: disabled 

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related