I am using below script to get service information from the windows guest os using invoke-vmscript but for few vms the credentials which i provided in the script are not valid so for those vms i am not getting any error output or vmname with blank result in output $report.
So is it possible to write the error output while using wait-task because when I look at the powershell console the wait-task is displaying the error 'Failed to authenticate with the guest operating system using the supplied credentials' but in the $task.Result.ScriptOutput is not showing up the authentication failed error and even $task.Result.VM.Name is not showing up the vm name.
I am ok for few vms if authentication failed or any other error but expecting to write that error in $report for those vmnames.
$script = @'
$output=Get-Service |select Name
$output.Name -join ','
'@
$tasks = @()
foreach($singlevm in Get-VM test01,test02,test03,test04,test05,test06,test07){
$sInvoke = @{
VM = $singlevm.Name
GuestUser = 'administrator'
GuestPassword = 'password'
ScriptText = $script
ScriptType = 'Powershell'
ErrorAction = 'Stop'
}
$tasks+=Invoke-VMScript @sInvoke -RunAsync -Confirm:$false
}
Wait-Task -Task $tasks -Verbose
$report=foreach ($task in $tasks) {
'' | Select-Object @{N='VM';E={$task.Result.VM.Name}},
@{N ='Result'; E={$task.Result.ScriptOutput.Split("`n") |Where-Object { $_ -ne '' } | %{$_.Trim("`r`n")}}}
}
$report
I had a typo in that last code.
It is corrected now.
And yes, you can bring it all together.
Something like this for example
$output=Get-Service |select Name
$output.Name -join ','
'@
$tasks = @()
foreach($singlevm in Get-VM 'Win2k16_Std_64bit-testClone'){
$sInvoke = @{
VM = $singlevm
GuestUser = 'administrator'
GuestPassword = 'password'
ScriptText = $script
ScriptType = 'Powershell'
RunAsync = $true
Confirm = $false
}
$tasks += @{
VM = $singlevm
Task = Invoke-VMScript @sInvoke
}
}
while($tasks.Task.State -contains 'Running'){
sleep 2
}
$tasks |
Select @{N='VM';E={$_.VM}},
@{N='State';E={$_.Task.State}},
@{N='Error';E={$_.Task.TerminatingError.Message}},
@{N ='Result'; E={$_.Task.Result.ScriptOutput.Split("`n") |Where-Object { $_ -ne '' } | %{$_.Trim("`r`n")}}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
If you run the same but without RunAsync and the Wait-Task, do all these calls to Invoke-VMScript return correctly?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
If I run like this nothing is captured in $tasks
$script = @'
$output=Get-Service |select Name
$output.Name -join ','
'@
$tasks = @()
foreach($singlevm in Get-VM 'Win2k16_Std_64bit-testClone'){
$sInvoke = @{
VM = $singlevm.Name
GuestUser = 'administrator'
GuestPassword = 'password'
ScriptText = $script
ScriptType = 'Powershell'
ErrorAction = 'Stop'
}
$tasks+=Invoke-VMScript @sInvoke
#-RunAsync -Confirm:$false
}
If you run without the RunAsync switch there is no Task returned by Invoke-VMScript.
But the result that you show seems to indicate that the supplied credentials are not correct for at least one of the targetted VMs.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
If you run without the RunAsync switch there is no Task returned by Invoke-VMScript.
I just tested for one vm for which credentials are wrong. For that error is not written in $tasks. It’s just showed up in PowerShell console which I showed in above snap.
But the result that you show seems to indicate that the supplied credentials are not correct for at least one of the targetted VMs.
Yeah I intentionally give wrong credentials to show you.
The error is not coming from the Guest OS on the target VM, but from the Invoke-VMScript cmdlet itself.
That explains why it is not in ScriptOutput.
The best way to catch incorrect credentials is to use a try-catch construct (I think we have discussed this before in some of your other threads).
That way you can intercept in the invalid credentials exception, report it and continue the script.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes LucD by using your last script I used try catch method now but its not giving any results. How to use with -RunAsync switch and Wait-Task -Task $tasks because I need to run on large set of vms and with -RunAsync will give results more quicker.
$script = @'
$output=Get-Service |select Name
$output.Name -join ','
'@
$tasks = @()
foreach($singlevm in Get-VM 'Win2k16_Std_64bit-testClone'){
try {
$sInvoke = @{
VM = $singlevm.Name
GuestUser = 'administrator'
GuestPassword = 'password'
ScriptText = $script
ScriptType = 'Powershell'
ErrorAction = 'Stop'
}
$tasks+=Invoke-VMScript @sInvoke -RunAsync -Confirm:$false
break
}
catch {
}
}
Wait-Task -Task $tasks -Verbose
$report=foreach ($task in $tasks) {
'' | Select-Object @{N='VM';E={$task.Result.VM.Name}},
@{N ='Result'; E={$task.Result.ScriptOutput.Split("`n") |Where-Object { $_ -ne '' } | %{$_.Trim("`r`n")}}}
}
$report
Ok, try-catch doesn't seem to work with a client-side task.
As an alternative I came up with the following.
It doesn't use the Wait-Task anymore, but uses a while-loop to wait till tasks have completed.
Then it splits out the ones in error and the ones that completed.
I used a hash table to keep track of the background tasks.
The reason is that a failed background task doesn't have the VM information anymore.
$output=Get-Service |select Name
$output.Name -join ','
'@
$tasks = @()
foreach($singlevm in Get-VM 'Win2k16_Std_64bit-testClone'){
$sInvoke = @{
VM = $singlevm
GuestUser = 'administrator'
GuestPassword = 'password'
ScriptText = $script
ScriptType = 'Powershell'
RunAsync = $true
Confirm = $false
}
$tasks += @{
VM = $singlevm
Task = Invoke-VMScript @sInvoke
}
}
while($tasks.Task.State -contains 'Running'){
sleep 2
}
$tasks | where{$_.Task.State -eq 'Error'} |
ForEach-Object -Process {
Write-Output "Call failed for $($_.VM) with error $($_.Task.TerminatingError.Message)"
}
$tasks | where{$_.Task.State -eq 'Success'} |
Select-Object @{N='VM';E={$_.Result.VM.Name}},
@{N ='Result'; E={$_.Result.ScriptOutput.Split("`n") |Where-Object { $_ -ne '' } | %{$_.Trim("`r`n")}}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Its not displaying any output for vms when authentication is success.
When authentication fails its writing the output.
I am also thinking instead of Write-Output can we keep it in one variable for both failure and success machines so that I can export to csv.
I had a typo in that last code.
It is corrected now.
And yes, you can bring it all together.
Something like this for example
$output=Get-Service |select Name
$output.Name -join ','
'@
$tasks = @()
foreach($singlevm in Get-VM 'Win2k16_Std_64bit-testClone'){
$sInvoke = @{
VM = $singlevm
GuestUser = 'administrator'
GuestPassword = 'password'
ScriptText = $script
ScriptType = 'Powershell'
RunAsync = $true
Confirm = $false
}
$tasks += @{
VM = $singlevm
Task = Invoke-VMScript @sInvoke
}
}
while($tasks.Task.State -contains 'Running'){
sleep 2
}
$tasks |
Select @{N='VM';E={$_.VM}},
@{N='State';E={$_.Task.State}},
@{N='Error';E={$_.Task.TerminatingError.Message}},
@{N ='Result'; E={$_.Task.Result.ScriptOutput.Split("`n") |Where-Object { $_ -ne '' } | %{$_.Trim("`r`n")}}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Some issue. I am not getting the output. Below is the output.
For the same VM if I execute as below I can see the output.
I think it is normal that there is nothing in Result when the State says 'error'
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
But if I execute for that same VM as below I got the result.
Invoke-VMScript -VM $singlevm -ScriptText $script -ScriptType Powershell -GuestUser 'administrator' -GuestPassword ''
Then you probably need to check what is in $sInvoke.
I can't really debug that if it is something on your side.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Looks like the copy/paste had an error.
The Invoke-VMScript was called twice. I corrected that
I just did some more testing with 2 targets, one with a correct password and one with an incorrect password.
And the result is what I expected.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes Thanks now its working with this version,
One last question for this thread Is it possible to capture failed and success output using wait-task because based on your last reply for my other thread(Same output is displayed multiple times ) I have created the script which I posed as question in this thread. Why I am wait-task is because the execution is very fast.
No, that's why I used the While-loop instead of Wait-Task.
Wait-Task shows the error and nothing else.
With the While-loop I can check the State of the Task.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Ok Thanks