I have a bunch of VMs in Azure I want to run the same script against. Because of reasons, I can't use powershell 7, so I have to use powershell 5. Which means I can use "foreach -parallel", but NOT "foreach-parallel". So it can work, but requires a workflow.
I have the following workflow that will grab the list of servers in a specific tenant/environment, and then run a foreach -parallel to run a script against each of them at the same time.
The problem I'm running into is that it appears to work, but the result I get out is:
Microsoft.Azure.Commands.Compute.Automation.Models.PSRunCommandResult
blah
Which is not the actual result (in this it would be the time). Because it's within a workflow, getting the details out is... painful. How do I get the results? It appears to run, there's no errors, but I can't figure out the results. Thanks.
The get-member on $out gives:
Name MemberType Definition
---- ---------- ----------
GetType Method type GetType()
ToString Method string ToString(), string ToString(string format, System.IFormatProvider formatProvider), string IFormattable.ToString(string format, System.I...
PSComputerName NoteProperty string PSComputerName=localhost
PSShowComputerName NoteProperty bool PSShowComputerName=True
PSSourceJobInstanceId NoteProperty guid PSSourceJobInstanceId=0870d1ff-1234-5678-014e-2e123456c7d8
Capacity Property System.Int32 {get;set;}
Count Property System.Int32 {get;set;}
EndTime Property {get;set;}
Error Property {get;set;}
Item Property {get;set;}
Name Property {get;set;}
Output Property {get;set;}
StartTime Property {get;set;}
Status Property System.String {get;set;}
Value Property Deserialized.System.Collections.Generic.List`1[[Microsoft.Azure.Management.Compute.Models.InstanceViewStatus, Microsoft.Azure.Management.Compu...
Microsoft.Azure.Commands.Compute.Automation.Models.PSRunCommandResult
And here's the script I'm running:
#for some reason you need to disconnect from one and then connect to the other, can't run two at once.
disconnect-azaccount
connect-azaccount -Tenant "mytenantid"
#get all the dev Windows VM servers in the current tenant that are turned on.
$serverinfo = @()
Get-AzContext -ListAvailable |where-object {$_.Name -like "*Dev*"}| %{
$_|select-azcontext
$serverinfo += get-azvm -status | Where-Object {$_.PowerState -eq "VM running" -and $_.StorageProfile.OSDisk.OSType -eq "Windows"}
}
#honestly, for the test I filtered down to the jumpboxes.
$serverinfo2 = $serverinfo|where {$_.Name -like "*jumpbox*"}
#workflows are needed; can't run foreach -parallel otherwise.
Workflow TestParallel{
#need to pass in the details, it can't reach the $serverinfo2 otherwise.
param($listofservers) #take serverinfo2 and make it accessible from within the workflow.
$test=@()
#need to set the proper context
Get-AzContext -ListAvailable |where-object {$_.Name -like "*Dev*"}| select-azcontext
#now we run each of these at the same time. Foreach-parallel requires 7, but we can do foreach -parallel within powershell 4 workflows.
Foreach -parallel($server in $listofservers){
#now that the script is on there, run the command locally.
$out = Invoke-AzVMRunCommand `
-ResourceGroupName $server.ResourceGroupName `
-Name $server.name `
-CommandId 'RunPowerShellScript' `
-ScriptString "$dt = gwmi win32_localtime; New-Object DateTime $dt.year,$dt.month,$dt.day,$dt.hour,$dt.minute, $dt.second"
#scriptstring is a newer command, added in july 2022
#Formating the Output with the VM name. Value[0].Message contains the results from running the script.
#export it to a variable that will survive the foreach
#$WORKFLOW:test += $server.Name + " " + $out.Value[0].Message
$WORKFLOW:test += $out.Value[1].Message #appears to be 1 now, using " -scriptstring"
#writing it locally to see if it shows up
"$out"
}
[array]$resultsArray = @($test)
write-output ("blah " + $test[0])
$resultsArray
}
TestParallel $serverinfo2