Sorting by (custom) expression output - powershell

So I have this as my current code:
Get-Process | Sort Valid,ProcessName |
Format-Table #{n='ProcessName';e={$_.ProcessName}},
#{n='Valid';e={if(($_.mainmodule.filename | Get-AuthenticodeSignature).Status -eq 'Valid') {1} else {0}}} -AutoSize
which gives me an output of:
ProcessName Valid
----------- -----
3DG4me 1
Adobe CEF Helper 1
Adobe CEF Helper 1
Adobe Desktop Service 1
AdobeIPCBroker 1
AdobeUpdateService 1
AGSService 1
ApplicationFrameHost 1
audiodg 0
avgnt 1
avguard 1
Avira.ServiceHost 1
Avira.Systray 1
avshadow 1
Calculator 0
CCLibrary 1
....etc etc
Even though I put a sort before I formatted it won't let me sort by Valid, which is an integer. I've tried adding [int] before {1} and {0} but it doesn't seem to be working.

You cannot sort by properties that aren't created until after the sorting happened. Valid is not a property of System.Diagnostic.Process objects. If you want to sort by that calculated property you need to add it before sorting. This insertion is usually done via Select-Object:
Get-Process |
Select-Object ProcessName,
#{n='Valid';e={if(($_.mainmodule.filename | Get-AuthenticodeSignature).Status -eq 'Valid') {1} else {0}}} |
Sort Valid, ProcessName |
Format-Table -AutoSize

Related

How to get a numbered count of different items in powershell

Im using the following powershell query to get a list of disks:
Get-NcDisk | Select-Object -Property model | Sort-Object -Property Model -Descending | foreach {$_.model}
It outputs like below:
X316_SMKRE06TA07
X316_HARIH06TA07
X316_HARIH06TA07
X316_HARIH06TA07
How can I get it to output a numbered count of each type of disk like below:
1 X316_SMKRE06TA07
3 X316_HARIH06TA07
Group-Object will do this for you..
I can't use Get-NcDisk but it may just be:
Get-NcDisk | Select-Object -ExpandProperty model | Group-Object
Example output using a string array:
"X316_SMKRE06TA07","X316_HARIH06TA07","X316_HARIH06TA07","X316_HARIH06TA07" | Group-Object
Count Name Group
----- ---- -----
1 X316_SMKRE06TA07 {X316_SMKRE06TA07}
3 X316_HARIH06TA07 {X316_HARIH06TA07, X316_HARIH06TA07, X316_HARIH06TA07}

How to get the value only from the Hashtable in PowerShell?

If I have a hastable $states = #{ 1 = 15; 2 = 5; 3 = 41 }, The result shows
Name Value
---- -----
3 41
2 5
1 15
I used $states.GetEnumerator() | sort value -Descending | select -Last 1 to find the minimum value that I need.
The result is:
Name Value
---- -----
2 5
However, I cannot use the value (5) as a new variable to do a calculation. This is due to the result cotains both name and value. Is there any method to get the minimum value only from the result?
Use the .Values property from the beginning:
$states.Values | Sort-Object -Descending | Select-Object -Last 1
Or expand the .Value property:
$states.GetEnumerator() | sort value -Descending | select -Last 1 -ExpandProperty Value

Returning the member in a group with the highest of a specific property

I'm trying to find the process with the highest CPU in a given group, in my case the group is simply by processname. Assume I have these processes running:
Id ProcessName CPU Memory Threads
-- ----------- --- ------ -------
7532 MicrosoftEdgeCP 40,3125 355,51953125 27
1680 powershell_ise 47,875 214,1015625 23
7568 lync 7,9375 213,859375 52
9664 chrome 19,71875 167,9609375 12
4216 MicrosoftEdgeCP 92,578125 152,2890625 26
5392 explorer 31,09375 116,390625 66
2676 chrome 23,390625 110,96875 41
9812 chrome 14,625 100,859375 8
2872 MsMpEng 100,5234375 36
5752 SearchUI 2,609375 90,0625 23
I'm trying to find Chrome (9664). Currently I have this code:
$list = #()
$grouped = Get-Process | Where ProcessName -Like "c*" |
Sort CPU -Descending |
Group ProcessName |
Select $_ -First 10
$grouped
foreach($item in $grouped) {
$list += #($item.Group |
Sort CPU -Descending |
Select Id, ProcessName, CPU, Memory, Threads -First 1)
}
$list | ft -Wrap
Is it possible to do the same without storing the first in each group in the $list array?
So you wanted to get the process where the CPU is the highest among the threads of the same name correct?
Get-Process -Name "c*" |
Sort-Object CPU -Descending |
Group ProcessName |
ForEach-Object{$_.Group | Select Id, ProcessName, CPU, Memory, Threads -First 1}
-Name supports wildcards so we can save returning all the processes just to drop most of them. Do the first sort and group on processname. Then just take the first entry from each individual group. The last for each is required to prevent the object array from being unrolled and only returning the highest overall entry.

PS: Filter selected rows with only max values as output?

I have a variable results ($result) of several rows of data or object like this:
PS> $result | ft -auto;
name value
---- -----
a 1
a 2
b 30
b 20
....
what I need to get all the rows of name and max(value) like this filtered output:
PS> $result | ? |ft -auto
name value
---- -----
a 2
b 30
....
Not sure what command or filters available (as ? in above) so that I can get each name and only the max value for the name out?
$result | group name | select name,#{n='value';e={ ($_.group | measure value -max).maximum}}
This should do the trick:
PS> $result | Foreach {$ht=#{}} `
{if ($_.Value -gt $ht[$_.name].Value) {$ht[$_.Name]=$_}} `
{$ht.Values}
This is essentially using the Begin/Process/End scriptblock parameters of the Foreach-Object cmdlet to stash input objects with a max value based on a key into a hashtable.
Note: watch out for extra spaces after the line continuation character (`) - there shouldn't be any.

Getting character count for each row in text doc

I am trying to get the character count for each row in a text doc. The contents of my text doc are:
1
15
69
124
300
I've been trying variants of the PS script:
get-content c:\serverlist.txt | foreach-object {measure-object -character}
But the best I can get returned is:
Lines Words Characters Property
------- -------- -------------- -----------
0 0 0 0 0
Not sure what I'm missing here, but any help would be appreciated!
Thanks!
You have to pipe directly into Measure-Object:
Get-Content c:\serverlist.txt | Measure-Object -Character
Otherwise you'd have to do either
| ForEach-Object { $_ | Measure-Object -Character }
which would be a bit of weird use of the pipeline or
| ForEach-Object { Measure-Object -Character -InputObject $_ }
which would be just about the same as the variant above.