PowerShell Format-List from different objects in the chain - powershell

How do I output properties from parent objects in a piped chain?
For example:
get-vm | get-vmdisk | forEach {Get-VHDInfo $_.DiskPath} | Select -Property Path, ParentPath, VM.VMElementName
Basically it's the VM.VMElementName that I'm wondering about (I made up that syntax). It's not the immediate object (which would be from Get-VHDInfo) but the grandparent (from get-vm) that I want to get a value for.

You cannot get values from upstream cmdlets the way you want to. You can use foreach-object right after calling get-vm and save the value in a variable, then assign it back to the select-object as a new calculated property.
get-vm | foreach-object{
$VMElementName = $_.VMElementName
get-vmdisk | forEach {Get-VHDInfo $_.DiskPath} | Select Path,ParentPath,#{Name='VMElementName';Expression={$VMElementName}}
}

Related

Select-Object - Keep default columns but add one

I can use Select-Object to choose which columns to show and even add calculated columns. An example:
gci | select *, #{n='LAS'; e={(Get-Date)-$_.LastAccessTime}}
I want add a calculated column but keep the defaut ones. Without the * wildcard I only get my calculated property. With it I get everything. The only workaround I've got to work is to manually list the default property names. Any ideas?
The thing is that that you actually states to display all properties ('*').
So to add to only the standard properties, you first need to get the standard properties.
[string[]]$StdProperties = (Get-ChildItem).PSStandardMembers.DefaultDisplayPropertySet[1].ReferencedPropertyNames
We don't actually want to change the standard property of the objects returned
Get-Childitem | select Name | Get-Member| group TypeName | select Name
Name
----
Selected.System.IO.DirectoryInfo
Selected.System.IO.FileInfo
So we just need to expand on that extracted string array with the new property to use.
$StdProperties += 'LAS'
And finally, to put it to use...
Get-ChildItem | select *, #{n='LAS'; e={(Get-Date) - $_.LastAccessTime}} |
select $StdProperties
Just for fun, building on Abrahams comment, you could do something weird like this:
# get the default properties used on Format-Table
$defaultProps = (((Get-ChildItem | Format-Table | Out-String) -split '\r?\n' |
Where-Object { $_ -match '^\w.*' }) |
Select-Object -First 1) -split '\s+' -ne ''
# now execute the command
Get-ChildItem | Select-Object *, #{n='LAS'; e={(Get-Date)-$_.LastAccessTime}} |
Select-Object ($defaultProps + 'LAS') | Format-Table -AutoSize

Possible to sort object by property (descending) and still display corresponding values?

$procs = Get-Process
$procs[0] | GM -MemberType Property
This gives all the properties in ascending order. Now, I'd like to display the properties in descending order but with it's values. It's easy to sort the properties themselves...
$procs[0] | GM -MemberType Property | Select-Object Name | Sort-Object -Descending -Property Name
...however this does not display the corresponding values.
I'm also able to sort values of one property in a descending manner but not sort by properties themselves.
EDIT: Here's a screenshot to better illustrate what I'd like to achieve:
What you can see here is the sample output of Get-Process | Where-Object { $_.Name -like "a*" } | Export-Csv -Path "$env:USERPROFILE\Desktop\example.csv"
As you can see the properties are not sorted. I would like to be able to output exactly what the screenshot shows but with the property columns and their corresponding values sorted in descending order, i.e. WS, VM, SI, PM, NPM, Name, Handles.
I hope I was able to clearly explain it now.
Thanks for your help.
It happens because, after all in your pipeline result is Hashtable with strings.
Save result in variable and give it into pipe like this,it's reveal each property in detail by putting Name of property after variable In "dot notation"
$propertys = (get-process)[0] | GM -MemberType Property | Select-Object Name | Sort-Object -Descending -Property Name
($propertys.NAME) | %{(get-process)[0].$_}
or use short presentation of properties by using FL
(get-process)[0] | fl $($propertys.Name[0..$propertys.Count])

Powershell get Get-Measure property value

How do I get to the Get-Measure Count property value through piping without surrounding with parenthesises? (Powershell version 5)
I would like something like alias | measure | $_.Count.
TL;DR
Say I want to count the number of aliases in Powershell so I go
alias | measure | Select-Object -Property Count
Which returns a PSCustomObject and not the Int32 I was looking for.
Instead I can
alias | measure | foreach { $_.Count }
which relies on Get-Measure returning one and only one object. It works for this simple case but is IMO even then ugly.
Another working solution is to
( alias | measure ).Count
but I really don't like having to surround with parenthesises, especially when the alias|..|..|..|measure code gets long.
Finally I could
alias | measure | % { $_.Count }
which seems to be the best. But the {...} annoys me.
This latter version is the best so far.
To "extract" a single property from a custom object you can use -ExpandProperty like this:
Get-Alias |
Measure-Object |
Select-Object -ExpandProperty Count

How to strip out everything but numbers in a variable?

I'm trying to automate setting an IP address through PowerShell and I need to find out what my interfaceindex number is.
What I have worked out is this:
$x = ( Get-NetAdapter |
Select-Object -Property InterfceName,InterfaceIndex |
Select-Object -First 1 |
Select-Object -Property Interfaceindex ) | Out-String
This will output:
InterfaceIndex
--------------
3
Now the problem, when I try to grab only the number using:
$x.Trim.( '[^0-9]' )
it still leave the "InterfaceIndex" and the underscores. This causes the next part of my script to error because I just need the number.
Any suggestions?
This will get your job done:
( Get-NetAdapter | Select-Object -Property InterfceName,InterfaceIndex | Select-Object -First 1 | Select-Object -Property Interfaceindex).Interfaceindex
Actually you do not need two times to select the property: do like this:
( Get-NetAdapter |Select-Object -First 1| Select-Object -Property InterfceName,InterfaceIndex).Interfaceindex
Answering your immediate question: you can remove everything that isn't a number from a variable by, well, removing everything that isn't a number (or rather digit):
$x = $x -replace '\D'
However, a better aproach would be to simply not add what you want removed in the first place:
$x = Get-NetAdapter | Select-Object -First 1 -Expand InterfaceIndex
PowerShell cmdlets usually produce objects as output, so instead of mangling these objects into string form and cutting away excess material you normally just expand the value of the particular property you're interested in.
(Get-NetAdapter | select -f 1).Interfaceindex
No point in selecting properties as they are there by default. If you want to keep object do:
(Get-NetAdapter | select -f 1 -ov 'variablename').Interfaceindex
where f = first, ov = outvariable
$variablename.Interfaceindex
You don't need Out-String as cast to string is implicit when you output to screen. and if you try to work with this data further down powershell is clever enough to cast it from int to string and vice versa when needed.

Why is this not working? - Trying to save properties in a variable for use multiple times in a function

I am trying to find a way to save the properties for a select statement in PowerShell but it isn't working. I haven't found a way to make an entire statement a literal so that it isn't reviewed until the variable is opened.
Here is what works:
$wsus.GetSummariesPercomputerTarget($CurrentMonthUpdateScope, $ComputerScope) |
Select-Object #{L="WSUSServer";E={$Server}},
#{L="FromDate";E={$($CurrentMonthUpdateScope.FromCreationDate).ToString("MM/dd/yyyy")}},
#{L="ToDate";E={$($CurrentMonthUpdateScope.ToCreationDate).ToString("MM/dd/yyyy")}},
#{L='Computer';E={($wsus.GetComputerTarget([guid]$_.ComputerTargetID)).FullDomainName}},
DownloadedCount,
NotInstalledCount,
InstalledPendingRebootCount,
FailedCount,
Installedcount |
Sort-Object -Property "Computer"
and I am trying to get the properties mentioned (starting just after the Select-Object statement and ending just before the last pipe) placed in a variable so that I can use the same properties multiple times with different scopes.
I have tried this:
$Properties = '#{L="WSUSServer";E={$Server}},
#{L="FromDate";E={$($CurrentMonthUpdateScope.FromCreationDate).ToString("MM/dd/yyyy")}},
#{L="ToDate";E={$($CurrentMonthUpdateScope.ToCreationDate).ToString("MM/dd/yyyy")}},
#{L="Computer";E={($wsus.GetComputerTarget([guid]$_.ComputerTargetID)).FullDomainName}},
DownloadedCount,
NotInstalledCount,
InstalledPendingRebootCount,
FailedCount,
Installedcount'
$wsus.GetSummariesPercomputerTarget($CurrentMonthUpdateScope, $ComputerScope) |
Select-Object $Properties |
Sort-Object -Property "Computer"
While this runs it doesn't give any data and I think it confuses PowerShell.
This gives the same response:
$Properties = "#{L=`"WSUSServer`";E={$Server}},
#{L=`"FromDate`";E={$($CurrentMonthUpdateScope.FromCreationDate).ToString(`"MM/dd/yyyy`")}},
#{L=`"ToDate`";E={$($CurrentMonthUpdateScope.ToCreationDate).ToString(`"MM/dd/yyyy`")}},
#{L=`"Computer`";E={($wsus.GetComputerTarget([guid]$_.ComputerTargetID)).FullDomainName}},
DownloadedCount,
NotInstalledCount,
InstalledPendingRebootCount,
FailedCount,
Installedcount"
Any options, thoughts, etc.?
The -Property argument of Select-Object expects an array, not a string. So something like this:
$Properties = #(#{L="WSUSServer";E={$Server}},
#{L="FromDate";E={$($CurrentMonthUpdateScope.FromCreationDate).ToString("MM/dd/yyyy")}},
#{L="ToDate";E={$($CurrentMonthUpdateScope.ToCreationDate).ToString("MM/dd/yyyy")}},
#{L="Computer";E={($wsus.GetComputerTarget([guid]$_.ComputerTargetID)).FullDomainName}},
"DownloadedCount",
"NotInstalledCount",
"InstalledPendingRebootCount",
"FailedCount",
"Installedcount")
Note, you will need to turn the simple property names into strings within your array.