Powershell workflow with "foreach -parallel" and Invoke-AZVMRunCommand- how to get results out?

Viewed 34

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
0 Answers
Related