When I use the Select-Object Name CmdLet it seems to create a new object with a single Name property on it.
I often want to pipe this selection to other CmdLets but they often take just a string.
How can I easily get a bunch of objects and say "Select only property x and just the property values into an array or collection of just its values"?
You can use the ExpandProperty parameter for this. This switch means that instead of returning an object with properties as listed on the (default) -Properties parameter, the value of the single property listed under -ExpandProperty parameter is returned.
NB: You can also use the alias, expand for this parameter.
Example:
Get-Process | Select-Object -ExpandProperty ProcessName
Related documentation:
SS64: https://ss64.com/ps/select-object.html
MS Docs: https://learn.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Select-Object?view=powershell-3.0
Related
This is how my current script looks like:
$cpu = Get-WmiObject win32_processor | select LoadPercentage
logwrite $cpu #this fuction writes $cpu into a .txt file
The output of the file is:
#{LoadPercentage=4}
I want it to be only the number so that I can make calculations.
qbanet359's helpful answer uses direct property access (.LoadPercentage) on the result object, which is the simplest and most efficient solution in this case.
In PowerShell v3 or higher this even works with extracting property values from a collection of objects, via a feature called member-access enumeration.
E.g., ((Get-Date), (Get-Date).AddYears(-1)).Year returns 2019 and 2018 when run in 2019, which are the .Year property values from each [datetime] instance in the array.
In cases where you do want to use Select-Object (or its built-in alias, select), such as when processing a large input collection item by item:
To use Select-Object to extract a single property value, you must use -ExpandProperty:
Get-WmiObject win32_processor | Select-Object -ExpandProperty LoadPercentage
Background:
Select-Object by default creates custom objects ([pscustomobject] instances[1]
) that have the properties you specify via the -Property parameter (optionally implicitly, as the 1st positional argument).
This applies even when specifying a single property[2], so that select LoadPercentage (short for: Select-Object -Property LoadPercentage) creates something like the following object:
$obj = [pscustomobject] #{ LoadPercentage = 4 } # $obj.LoadPercentage yields 4
Because you use Add-Content to write to your log file, it is the .ToString() string representation of that custom object that is written, as you would get if you used the object in an expandable string (try "$([pscustomobject] #{ LoadPercentage = 4 })").
By contrast, parameter -ExpandProperty, which can be applied to a single property only, does not create a custom object and instead returns the value of that property from the input object.
Note: If the value of that property happens to be an array (collection), its elements are output individually; that is, you'll get multiple outputs per input object.
[1] Strictly speaking, they're [System.Management.Automation.PSCustomObject] instances, whereas type accelerator [pscustomobject], confusingly, refers to type [System.Management.Automation.PSObject], for historical reasons; see this GitHub issue.
[2] There's a hotly debated request on GitHub to change Select-Object's default behavior with only a single property; while the discussion is interesting, the current behavior is unlikely to change.
That is a pretty simple fix. Instead of selecting the LoadPercentage when running Get-WmiObject, just select the property when calling your function. This will write only the number to your log file.
$cpulogpath = "C:\Monitoring\$date.csv"
function logwrite
{
param ([string]$logstring)
add-content $cpulogpath -value $logstring
}
$cpu = Get-WmiObject win32_processor #don't select the property here
logwrite $cpu.LoadPercentage #select it here
This is how my current script looks like:
$cpu = Get-WmiObject win32_processor | select LoadPercentage
logwrite $cpu #this fuction writes $cpu into a .txt file
The output of the file is:
#{LoadPercentage=4}
I want it to be only the number so that I can make calculations.
qbanet359's helpful answer uses direct property access (.LoadPercentage) on the result object, which is the simplest and most efficient solution in this case.
In PowerShell v3 or higher this even works with extracting property values from a collection of objects, via a feature called member-access enumeration.
E.g., ((Get-Date), (Get-Date).AddYears(-1)).Year returns 2019 and 2018 when run in 2019, which are the .Year property values from each [datetime] instance in the array.
In cases where you do want to use Select-Object (or its built-in alias, select), such as when processing a large input collection item by item:
To use Select-Object to extract a single property value, you must use -ExpandProperty:
Get-WmiObject win32_processor | Select-Object -ExpandProperty LoadPercentage
Background:
Select-Object by default creates custom objects ([pscustomobject] instances[1]
) that have the properties you specify via the -Property parameter (optionally implicitly, as the 1st positional argument).
This applies even when specifying a single property[2], so that select LoadPercentage (short for: Select-Object -Property LoadPercentage) creates something like the following object:
$obj = [pscustomobject] #{ LoadPercentage = 4 } # $obj.LoadPercentage yields 4
Because you use Add-Content to write to your log file, it is the .ToString() string representation of that custom object that is written, as you would get if you used the object in an expandable string (try "$([pscustomobject] #{ LoadPercentage = 4 })").
By contrast, parameter -ExpandProperty, which can be applied to a single property only, does not create a custom object and instead returns the value of that property from the input object.
Note: If the value of that property happens to be an array (collection), its elements are output individually; that is, you'll get multiple outputs per input object.
[1] Strictly speaking, they're [System.Management.Automation.PSCustomObject] instances, whereas type accelerator [pscustomobject], confusingly, refers to type [System.Management.Automation.PSObject], for historical reasons; see this GitHub issue.
[2] There's a hotly debated request on GitHub to change Select-Object's default behavior with only a single property; while the discussion is interesting, the current behavior is unlikely to change.
That is a pretty simple fix. Instead of selecting the LoadPercentage when running Get-WmiObject, just select the property when calling your function. This will write only the number to your log file.
$cpulogpath = "C:\Monitoring\$date.csv"
function logwrite
{
param ([string]$logstring)
add-content $cpulogpath -value $logstring
}
$cpu = Get-WmiObject win32_processor #don't select the property here
logwrite $cpu.LoadPercentage #select it here
This is how my current script looks like:
$cpu = Get-WmiObject win32_processor | select LoadPercentage
logwrite $cpu #this fuction writes $cpu into a .txt file
The output of the file is:
#{LoadPercentage=4}
I want it to be only the number so that I can make calculations.
qbanet359's helpful answer uses direct property access (.LoadPercentage) on the result object, which is the simplest and most efficient solution in this case.
In PowerShell v3 or higher this even works with extracting property values from a collection of objects, via a feature called member-access enumeration.
E.g., ((Get-Date), (Get-Date).AddYears(-1)).Year returns 2019 and 2018 when run in 2019, which are the .Year property values from each [datetime] instance in the array.
In cases where you do want to use Select-Object (or its built-in alias, select), such as when processing a large input collection item by item:
To use Select-Object to extract a single property value, you must use -ExpandProperty:
Get-WmiObject win32_processor | Select-Object -ExpandProperty LoadPercentage
Background:
Select-Object by default creates custom objects ([pscustomobject] instances[1]
) that have the properties you specify via the -Property parameter (optionally implicitly, as the 1st positional argument).
This applies even when specifying a single property[2], so that select LoadPercentage (short for: Select-Object -Property LoadPercentage) creates something like the following object:
$obj = [pscustomobject] #{ LoadPercentage = 4 } # $obj.LoadPercentage yields 4
Because you use Add-Content to write to your log file, it is the .ToString() string representation of that custom object that is written, as you would get if you used the object in an expandable string (try "$([pscustomobject] #{ LoadPercentage = 4 })").
By contrast, parameter -ExpandProperty, which can be applied to a single property only, does not create a custom object and instead returns the value of that property from the input object.
Note: If the value of that property happens to be an array (collection), its elements are output individually; that is, you'll get multiple outputs per input object.
[1] Strictly speaking, they're [System.Management.Automation.PSCustomObject] instances, whereas type accelerator [pscustomobject], confusingly, refers to type [System.Management.Automation.PSObject], for historical reasons; see this GitHub issue.
[2] There's a hotly debated request on GitHub to change Select-Object's default behavior with only a single property; while the discussion is interesting, the current behavior is unlikely to change.
That is a pretty simple fix. Instead of selecting the LoadPercentage when running Get-WmiObject, just select the property when calling your function. This will write only the number to your log file.
$cpulogpath = "C:\Monitoring\$date.csv"
function logwrite
{
param ([string]$logstring)
add-content $cpulogpath -value $logstring
}
$cpu = Get-WmiObject win32_processor #don't select the property here
logwrite $cpu.LoadPercentage #select it here
This is how my current script looks like:
$cpu = Get-WmiObject win32_processor | select LoadPercentage
logwrite $cpu #this fuction writes $cpu into a .txt file
The output of the file is:
#{LoadPercentage=4}
I want it to be only the number so that I can make calculations.
qbanet359's helpful answer uses direct property access (.LoadPercentage) on the result object, which is the simplest and most efficient solution in this case.
In PowerShell v3 or higher this even works with extracting property values from a collection of objects, via a feature called member-access enumeration.
E.g., ((Get-Date), (Get-Date).AddYears(-1)).Year returns 2019 and 2018 when run in 2019, which are the .Year property values from each [datetime] instance in the array.
In cases where you do want to use Select-Object (or its built-in alias, select), such as when processing a large input collection item by item:
To use Select-Object to extract a single property value, you must use -ExpandProperty:
Get-WmiObject win32_processor | Select-Object -ExpandProperty LoadPercentage
Background:
Select-Object by default creates custom objects ([pscustomobject] instances[1]
) that have the properties you specify via the -Property parameter (optionally implicitly, as the 1st positional argument).
This applies even when specifying a single property[2], so that select LoadPercentage (short for: Select-Object -Property LoadPercentage) creates something like the following object:
$obj = [pscustomobject] #{ LoadPercentage = 4 } # $obj.LoadPercentage yields 4
Because you use Add-Content to write to your log file, it is the .ToString() string representation of that custom object that is written, as you would get if you used the object in an expandable string (try "$([pscustomobject] #{ LoadPercentage = 4 })").
By contrast, parameter -ExpandProperty, which can be applied to a single property only, does not create a custom object and instead returns the value of that property from the input object.
Note: If the value of that property happens to be an array (collection), its elements are output individually; that is, you'll get multiple outputs per input object.
[1] Strictly speaking, they're [System.Management.Automation.PSCustomObject] instances, whereas type accelerator [pscustomobject], confusingly, refers to type [System.Management.Automation.PSObject], for historical reasons; see this GitHub issue.
[2] There's a hotly debated request on GitHub to change Select-Object's default behavior with only a single property; while the discussion is interesting, the current behavior is unlikely to change.
That is a pretty simple fix. Instead of selecting the LoadPercentage when running Get-WmiObject, just select the property when calling your function. This will write only the number to your log file.
$cpulogpath = "C:\Monitoring\$date.csv"
function logwrite
{
param ([string]$logstring)
add-content $cpulogpath -value $logstring
}
$cpu = Get-WmiObject win32_processor #don't select the property here
logwrite $cpu.LoadPercentage #select it here
How do you concatenate a string literal and parameter in a Select-Object.
For Example I have:
Get-AdUser -filter * | Select-Object 'sip'+SamAccountName,Name, Email, etc
Basically I want to return the property SamAccountName from the AdUser with the string literal sip before it.
I tried everything I can think of.
Thanks!
Edit: added parameters and multiple users
You can specify an expression in a script block to do this. Like this:
Get-AdUser foo#bar.com | select-object {"sip"+$_.SamAccountName}
Though if you do it this way, the name of resultant property looks a bit weird. To specify the property name as well, enclose the script block as part of a hashtable that specifies the name of the new property as well as the scriptblock expression to generate it. It would look like this:
Get-AdUser foo#bar.com | select-object #{name="SamAccountName"; expression={"sip"+$_.SamAccountName}}
You don't need to use Select-Object, because you're not trying to create a new object with specific properties; you're trying to select a single property (SamAccountName) and manipulate it.
"sip" + (Get-ADUser foo#bar.com).SamAccountName