PowerShell Job.Progress contains multiple objects - powershell

I am currently developing a backup manager for Hyper-V using PowerShell.
I ran into problems when starting an export job like this:
$job = (export-vm -name "Windows 10" -path F:\VM_Backup\ -asjob)
Now when querying the progress of the job I realized that two objects are inside my Progress property:
> $job.progress
ActivityId : 0
ParentActivityId : -1
Activity : Export wird ausgeführt
StatusDescription : Gelöscht
CurrentOperation :
PercentComplete : 1
SecondsRemaining : -1
RecordType : Processing
ActivityId : 0
ParentActivityId : -1
Activity : Export wird ausgeführt
StatusDescription : Gelöscht
CurrentOperation :
PercentComplete : 37
SecondsRemaining : -1
RecordType : Processing
While the second progress update makes real progress (increasing percentage), the first one always stays like above.
I have never seen this behavior before and that really doesn't make any sense to me. How do I (programmatically) select the "right" job?

By design, the .Progress property collects all progress messages written by the job - it doesn't just reflect the latest status.
The most recently written message is the last one added to the .Progress collection, so you can use index [-1] to retrieve it.
$job.Progress[-1]
Note: For Start-Job-created jobs, you must access the .Progress property on the (one and only) child job instead: $job.ChildJobs[0].Progress[-1] - see about_Job_Details.

Related

PowerShell - extracting nested object

I am fairly new to PowerShell and am trying to use a module called PoshWAPI. This module is used to query Infoblox. One of the commands is Get-IBobject which allows me to query infoblox for a record type.
This is my code so far:
Set-IBConfig -ProfileName 'MyGrid' -WAPIHost dns.example.com -WAPIVersion latest -Credential (Get-Credential) -SkipCertificateCheck
$result = Get-IBObject -ObjectType record:host 'name=host1.network.example.com' -ReturnAll
That works well and returns the following
_ref : record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LnRtY3MuaW5mb3NlYy5zMGE0OTFlMDAtMjMudDkwNC5zb25lc3N1czAx:host1.network.example.com/default
allow_telnet : False
comment : TOSD-37248
configure_for_dns : True
ddns_protected : False
disable : False
disable_discovery : False
dns_name : host1.network.example.com
extattrs :
ipv4addrs :{#{_ref=record:host_ipv4addr/ZG5zLmhvc3RfYWRkcmVzcyQuX2RlZmF1bHQudG1jcy5pbmZvc2VjLnMwYTQ5MWUwMC0yMy50OTA0LnNvbmVzc3VzMDEuMTAuNzMuMzAuMTYu:10.73.30.16/host1.network.example.com/default;
configure_for_dhcp=False; host=host1.network.example.com; ipv4addr=10.73.30.16}}
name : host1.network.example.com
network_view : default
rrset_order : cyclic
use_cli_credentials : False
use_snmp3_credential : False
use_snmp_credential : False
use_ttl : False
view : default
zone : network.example.com
The info I actually require from there are the name field and within the ipv4addrs field is a field called ipv4addr.
Currently I export it all to CSV using this command
$result | Export-Csv -Path C:\Users\neil.bloyce\Documents\2023\2.Feb\InfoBlox.csv
It isn't elegant but gets some of the info I want, however within the ipv4addrs I don't get any info except for System.Object[].
How do I adjust my code so that I can pull the ipv4addr out of ipv4addrs so I can see it in the CSV, Ideally the only info I actually need is dns_name and ipv4addr.
I am not sure how I attach the CSV file.
Kind regards
Use the Select-Object cmdlet to copy and transform only a subset of the properties from the object:
$result |Select-Object Name,#{Name='Addresses';Expression={ $_.ipv4addrs.ipv4addr -join ', ' }} |Export-Csv -Path C:\Users\neil.bloyce\Documents\2023\2.Feb\InfoBlox.csv -NoTypeInformation
Here, we extract the Name property from the original object, and then create a new calculated property that extracts the nested ipv4addr values and joins them together in a single string (thus causing Export-Csv to render the value correctly).

Trouble comparing JSON (or custom PS) objects

I am having trouble with object comparison.
I have an application which spits out JSON data. Each time I run my script, I will get the current values and import the stored values from the previous run (either from a .json or .xml file). At the end of the script, I will overwrite the stored values with the current values. The data looks like this:
Stored values:
id : 6549888
description : Windows CPU via WMI
name : Test
dataPoints : {#{id=6314; dataSourceId=6549888; name=CPUBusyPercent; description=%
of Busy CPU; alertTransitionInterval=8; alertClearTransitionInterval=0; type=2; dataType=2;
maxDigits=4; postProcessorMethod=expression;
postProcessorParam=100-(PercentProcessorTime/100000); rawDataFieldName=; maxValue=; minValue=0;
userParam1=; userParam2=; userParam3=; alertForNoData=3; alertExpr=>= 50 60 70; alertSubject=CPU
alert on ##HOST##; alertBody=The host ##HOST## is in state ##LEVEL##. CPU is ##VALUE## percent
busy - it has been in this state since ##START##, or for ##DURATION##}}
Current values:
id : 6549888
description : Windows CPU via WMI
name : Test
dataPoints : {#{id=6314; dataSourceId=6549888; name=CPUBusyPercent; description=%
of Busy CPU; alertTransitionInterval=8; alertClearTransitionInterval=0; type=2; dataType=2;
maxDigits=4; postProcessorMethod=expression;
postProcessorParam=100-(PercentProcessorTime/100000); rawDataFieldName=; maxValue=; minValue=0;
userParam1=; userParam2=; userParam3=; alertForNoData=3; alertExpr=>= 90 95 98; alertSubject=CPU
alert on ##HOST##; alertBody=The host ##HOST## is in state ##LEVEL##. CPU is ##VALUE## percent
busy - it has been in this state since ##START##, or for ##DURATION##}}
In this example, someone changed the alertExpr from "50 60 70" to "90 95 98" and I need to catch that (along with changes made to the rest of the properties).
When I run a foreach loop, I am not getting back any differences, but when I look at a single property, Powershell does report the difference. So the following returns nothing:
foreach ($dataSource in $currentDataSources) {
foreach ($recordedDatasource in $previousDataSources) {
If ($dataSource.id -eq $recordedDatasource.id) {
Compare-Object $dataSource $recordedDatasource
}
}
}
But looking at the index 1034 (that's my test item) does show a difference:
Compare-Object $currentDataSources[1034].datapoints.alertexpr $previousDatasources[1034].datapoints.alertexpr
What is the best way to check each of the properties between my to sets of data?
Thanks.

Powershell command $table.Columns.Add("NewFieldName") results in unexpected output to console

The following PowerShell script results in unexpected, and in my case unwanted, output to the console:
$table = New-Object System.Data.DataTable
$table.Columns.Add("NewFieldName")
Unexpected output:
AllowDBNull : True
AutoIncrement : False
AutoIncrementSeed : 0
AutoIncrementStep : 1
Caption : NewFieldName
ColumnName : NewFieldName
Prefix :
DataType : System.String
DateTimeMode : UnspecifiedLocal
DefaultValue :
Expression :
ExtendedProperties : {}
MaxLength : -1
Namespace :
Ordinal : 0
ReadOnly : False
Table : {}
Unique : False
ColumnMapping : Element
Site :
Container :
DesignMode : False
Expected output:
 
My questions are:
Why?
How can I prevent this output from going out to the console with the rest of my output?
TLDR: Add [void] like this
[void]$table.Columns.Add("NewFieldName")
Why? Because PowerShell tends to output the command's return value/object to the console (or whatever is receiving the output) by default.
How can I prevent this output from going out to the console with the rest of my output? Thank you to #PetSerAl for pointing out the solution of adding [void] to the left of the command. This casts the command's return type to a [void] which will not output to the console.
After #PetSerAl pointed me in the right direction I found these pages that helped clear things up:
Into the [void]
Gotcha #10 in PowerShell Gotchas

How to prevent Powershell not showing script processing data

I have created a powershell script for updating SharePoint List. When i run it shows all the backend processing to the console for example all the list schema info. I want it only show script created Out put (The only output with Write-Host) and not out of the box backend processing. Is there any command available to prevent that?
it shows counting like below when I use .add method of ArrayList where ever in script
0
1
2
3
and it shows List XML Schema when i store List items in some variable in the script like below:
Sealed : False
Version : 28
DisplayFormTemplateName : DocumentLibraryForm
EditFormTemplateName : DocumentLibraryForm
NewFormTemplateName : DocumentLibraryForm
NewFormUrl :
MobileNewFormUrl :
EditFormUrl :
MobileEditFormUrl :
DisplayFormUrl :
MobileDisplayFormUrl :
Id : 0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF39009893A4DD0A05487AAE05EAE8D183333C003933922476541344B8A065CBACE8178D
ReadOnly : False
Name : NewsPage
NameResource : Microsoft.SharePoint.SPUserResource
FeatureId : 00000000-0000-0000-0000-000000000000
Description : Used to create news articles.
JSLink :
DescriptionResource : Microsoft.SharePoint.SPUserResource
Hidden : False
Some .Net Methods and external programs output their exit code and other output to stdout.
You can either add the void keyword to the arraylist "Add" command or pipe it to Out-Null
$MyList = [System.Collections.ArrayList]#()
1..10 | % { $MyList.Add($_) } # outputs 0 to 9
1..10 | % { [void]$MyList.Add($_) } # no output
1..10 | % { $MyList.Add($_) | Out-Null } # no output

Debugging a FileQueueError using Swfupload

My swfupload implementation is triggering the fileQueueError function when I try to select multiple files. When I select one file the upload works as expected.
I'm logging the variables passed to the javascript functions and here's what I get anytime I select more than one file.
fileQueueError
file : null
errorCode : -100
message : 1
fileDialogComplete
Anyone got suggestions on how to trace the source of the error?
According to the file SWFUpload.js:
SWFUpload.QUEUE_ERROR = {
QUEUE_LIMIT_EXCEEDED : -100,
FILE_EXCEEDS_SIZE_LIMIT : -110,
ZERO_BYTE_FILE : -120,
INVALID_FILETYPE : -130
};
so,QUEUE_LIMIT_EXCEEDED