I am using the command wmic process get caption, virtualsize which returns 2 columns. I want to format the output in sorted manner based on virtualsize parameter. I tried to run the command in powershell and use sort-object cmdlet, but it appears that wmic does not return system objects which powershell can work upon.
Actual use-case it to fetch name of top 5 memory consuming process. Any help regarding this is appreciable.
wmic is a command-line interface to WMI intended for being used in CMD. Its output is an array of strings, which you'd have to transform into an array of objects with the fields as properties if you want to sort the output by a particular field. While that's possible, it's utterly pointless, because PowerShell has a cmdlet Get-WMIObject that provides the same functionality as wmic, but already produces objects that can be piped into the Sort-Object cmdlet:
Get-WMIObject Win32_Process |
Select-Object Caption, VirtualSize |
Sort-Object VirtualSize
or shorter:
gwmi Win32_Process | select Caption, VirtualSize | sort VirtualSize
Related
In a nutshell I'm trying to get what would be the output of this command to run.
Get-Process | Format-Table | sort-object Handles
Yes, I know you usually sort BEFORE Format-Table, but in this case I've created a hash-table within the Format-Table command that needs to be sorted. The problem is, there is no way to sort with Format-Table that I can figure out.
I also considered trying to output the FT to CSV and then massaging it but that didn't work for me either.
I'm expecting to get a sorted table.
I've created a hash-table within the Format-Table command that needs to be sorted
By definition, you can not output a hashtable via any of the -Format-* cmdlets:
Format-* cmdlets emit output objects whose sole purpose is to provide formatting instructions to PowerShell's for-display output-formatting system. In short: only ever use Format-* cmdlets to format data for display, never for subsequent programmatic processing - see this answer for more information.
Assuming you've used calculated properties, with Format-Table, use them with Select-Object instead, which produces data output, namely in the form of [pscustomobject] instances whose properties you can sort by, via Sort-Object.
For instance, the following creates custom objects with .Name and .MemUse properties and sorts by the latter, then outputs the top 10 results:
Get-Process |
Select-Object Name, #{ Name = 'MemUse'; Expression = 'WorkingSet64' } |
Sort-Object -Descending MemUse |
Select-Object -First 10
Inverting the logic and letting Sort-Object operate on the original objects output by Get-Process is more efficient:
Get-Process |
Sort-Object -Descending WorkingSet64 |
Select-Object -First 10 |
Select-Object Name, #{ Name = 'MemUse'; Expression = 'WorkingSet64' }
If you only care about for-display output, you can replace Select-Object Name, ... with Format-Table -Name, ... or Format-List -Name, ..., which illustrates an important point: Format-* calls should generally only come last in a pipeline.
I have declared 2 PowerShell variables
$prm=Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'Wolters Kluwer Financial Services'" | Select-Object Name, Vendor, Version
$rgteng=Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'WKFS'" | Select-Object Name, Vendor, Version
I want the output of this variable to a text file o/p #{Name=Wolters Kluwer Financial Services Regulatory Reporting FRA Param 11.2.0; Vendor=Wolters Kluwer Financial Services; Version=11.2.0}, I want this o/p to a text file.
I have tried using Write-Output and Write-Host, but none of them gives right o/p
What happens there looks like this (just the big picture):
Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'Wolters Kluwer Financial Services'" creates an WMI object and pipes it to the next command
Select-Object Name, Vendor, Version transforms that object into a new PSCustom type object (more like a table version of your WMI object wtih only the desired information)
Then it gets messy :
if you use write-host or display it on the screen , the output will be formatted according the the powershell's settings (those settings can be changed by altering xml files)
if you use export-csv you basically use a convertto-csv | out-file c:\sometheing.txt + some formatting rules that are applied. (I think the UTF-8 type of the file is changed but I am not sure...)
So if you want to know exactly how your variable / file will look like, without having powershell formatting interfering with your work, use convertto-csv | out-file.
I have a script that creates several jobs and stores two simple values in the jobs.
Start-Job -ScriptBlock {param ([string]$compip) tnc $compip | select RemoteAddress,PingSucceeded -WarningAction SilentlyContinue} -ArgumentList $compip
This works fine. What I would like to know is how can I store the following code into a variable?
Get-Job | Receive-Job | sort RemoteAddress | FT
I have tried this, but it does not work as I thought it would:
$pcs = Get-Job | Receive-Job | sort RemoteAddress | FT
$pcs.RemoteAddress
Am I going at this the wrong way? I would like to store the data from the get-job command above to use the values later in the script. I assumed it would work because the output looks correct:
Command:
Get-Job | Receive-Job | sort RemoteAddress | FT
Output:
RemoteAddress PingSucceeded
------------- -------------
192.168.0.163 True
192.168.0.101 False
192.168.0.2 False
192.168.0.251 True
Problem with Format-cmdlets
The issue here is your use of FT which is an alias for Format-Table. These Format- cmdlets are designed for console/screen output only. There are many things you can do with them to tailor that output but in every case PowerShell needs to massage the data in order to be able to do so. This includes breaking down to the passed objects into groups of different objects...
Microsoft.PowerShell.Commands.Internal.Format.FormatEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
The above data types were extract from running this code.
Get-ChildItem c:\temp | Format-Table | Get-Member
So you no longer have the System.IO.FileInfo and System.IO.DirectoryInfo objects that you would normally get from Get-ChildItem
Another large issue comes from Format-cmdlets nature to truncated data, like arrays with a large numbers of elements or long strings, to make as much fit on screen. In the case of arrays, this is due to the preference variable $FormatEnumerationLimit which is commonly defaulted to 4.
Ten Numbers
-----------
{1, 2, 3, 4...}
These, and other, limitations can all be mitigated with cmdlet switches like -AutoSize and -HideTableHeaders, out-string -width, etc. That does not matter however because...
Solution
Good news is the solution is very simple. Stop using them for anything other than console output. Using my earlier example:
Saving results in a variable?: $result = Get-ChildItem C:\temp
Exporting Data: Get-ChildItem C:\temp | Export-CSV $path -NoTypeInformation. Other Export-cmdlets could be preferred here like Export-CLIXml for complex objects when you want to store them for use elsewhere. If you are just looking for something pretty to include in your output then consider ConvertTo-HTML instead.
Extracting individual properties?: Just use Select-Object. $result | Select prop1, prop2. You can also expand your property selection to just get the strings or string array with -ExpandProperty: $result | Select -ExpandProperty prop1
Performing inline calculations with said properties?: Use calculated expression just as you would with the Format-Cmdlets. $result | Select prop1, #{Name="prop2";Expression={$_.prop2 * 3}
Potential Acceptable Use
Some prefer the output for use in emails and for recording statistics. While it is integral to keep data in its more easily used format for later use. However if you really need that data keep in mind that you are not working with the object your originally had anymore.
So if you needed your data in a table format but stored as a string then consider Out-String
$body = Get-ChildItem c:\temp | Format-Table | Out-String
but remember that Format-Table will play with object output in order to get it to display on screen (truncated array properties and long strings). Really.. if you wanted it nice and formatted then you should just use ConvertTo-HTML.
Point is you almost never need to keep the data from Format-Table. There is almost always a better way.
I have a script that creates several jobs and stores two simple values in the jobs.
Start-Job -ScriptBlock {param ([string]$compip) tnc $compip | select RemoteAddress,PingSucceeded -WarningAction SilentlyContinue} -ArgumentList $compip
This works fine. What I would like to know is how can I store the following code into a variable?
Get-Job | Receive-Job | sort RemoteAddress | FT
I have tried this, but it does not work as I thought it would:
$pcs = Get-Job | Receive-Job | sort RemoteAddress | FT
$pcs.RemoteAddress
Am I going at this the wrong way? I would like to store the data from the get-job command above to use the values later in the script. I assumed it would work because the output looks correct:
Command:
Get-Job | Receive-Job | sort RemoteAddress | FT
Output:
RemoteAddress PingSucceeded
------------- -------------
192.168.0.163 True
192.168.0.101 False
192.168.0.2 False
192.168.0.251 True
Problem with Format-cmdlets
The issue here is your use of FT which is an alias for Format-Table. These Format- cmdlets are designed for console/screen output only. There are many things you can do with them to tailor that output but in every case PowerShell needs to massage the data in order to be able to do so. This includes breaking down to the passed objects into groups of different objects...
Microsoft.PowerShell.Commands.Internal.Format.FormatEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
The above data types were extract from running this code.
Get-ChildItem c:\temp | Format-Table | Get-Member
So you no longer have the System.IO.FileInfo and System.IO.DirectoryInfo objects that you would normally get from Get-ChildItem
Another large issue comes from Format-cmdlets nature to truncated data, like arrays with a large numbers of elements or long strings, to make as much fit on screen. In the case of arrays, this is due to the preference variable $FormatEnumerationLimit which is commonly defaulted to 4.
Ten Numbers
-----------
{1, 2, 3, 4...}
These, and other, limitations can all be mitigated with cmdlet switches like -AutoSize and -HideTableHeaders, out-string -width, etc. That does not matter however because...
Solution
Good news is the solution is very simple. Stop using them for anything other than console output. Using my earlier example:
Saving results in a variable?: $result = Get-ChildItem C:\temp
Exporting Data: Get-ChildItem C:\temp | Export-CSV $path -NoTypeInformation. Other Export-cmdlets could be preferred here like Export-CLIXml for complex objects when you want to store them for use elsewhere. If you are just looking for something pretty to include in your output then consider ConvertTo-HTML instead.
Extracting individual properties?: Just use Select-Object. $result | Select prop1, prop2. You can also expand your property selection to just get the strings or string array with -ExpandProperty: $result | Select -ExpandProperty prop1
Performing inline calculations with said properties?: Use calculated expression just as you would with the Format-Cmdlets. $result | Select prop1, #{Name="prop2";Expression={$_.prop2 * 3}
Potential Acceptable Use
Some prefer the output for use in emails and for recording statistics. While it is integral to keep data in its more easily used format for later use. However if you really need that data keep in mind that you are not working with the object your originally had anymore.
So if you needed your data in a table format but stored as a string then consider Out-String
$body = Get-ChildItem c:\temp | Format-Table | Out-String
but remember that Format-Table will play with object output in order to get it to display on screen (truncated array properties and long strings). Really.. if you wanted it nice and formatted then you should just use ConvertTo-HTML.
Point is you almost never need to keep the data from Format-Table. There is almost always a better way.
An example
get-process | select-object vm, cpu,id | out-gridview
Here select-object actually is selecting PROPERTIES of the OBJECTS in the COLLECTION stored in memory.
Anyone knows why this cmdlet is not called select-property ?
Maybe I m asking a noob quesiton......
When you call Select-Object Blah, Blah1, Blah2, you are using the Property parameter via positional binding
Notice that the help describes a lot more than just the -Property parameter you are using:
Get-Help Select-Object -Full
<#
...
The Select-Object cmdlet selects specified properties of an object or set
of objects. It can also select unique objects, a specified number of
objects, or objects in a specified position in an array.
To select objects from a collection, use the First, Last, Unique, Skip, and
Index parameters. To select object properties, use the Property parameter.
When you select properties, Select-Object returns new objects that have
only the specified properties.
#>
Spend some time using the built in help system, there is a trove of information in there!
#Get the full help details
Get-Help Select-Object -Full
#If available, look online for help
Get-Help Select-Object -Online
#List conceptual topics
Get-Help about_*
#Read about regular expressions
Get-Help about_Regular_Expressions
Lastly, if you're talking semantics, the noun in a PowerShell command name refers to what your verb is acting upon: objects.
Cheers!