Reputation: 89
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
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.
Upvotes: 1
Views: 1090
Reputation: 440317
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, ...
Note:
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) value tuples (System.ValueTuple<T1, T2>
), 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 value tuples).
# Note that the properties containing the tuple elements are
# named .Item1 and .Item2, but PowerShell allows you to access them
# by positional index too.
[Linq.Enumerable]::Zip($services, $startupTypes) | ForEach-Object {
"service: {0}; startup type: {1}" -f $_[0], $_[1]
}
Generally, note that PowerShell, as of 7.3, 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 GitHub issue #2226 and GitHub issue #5146.
The above yields:
service: serviceA; startup type: automatic
service: serviceB; startup type: manual
service: serviceC; startup type: disabled
Upvotes: 1