Displaying results where count equals value - powershell

I want to identify the top few processes by average CPU usage over a period of couple of seconds. Each result needs to list the PID, Process Name and UserID.
The script needs to be run on several servers at the same time that are in another domain. The credentials for those servers are different to the computer it is being run from.
I can’t get Get-Process to work as it doesn’t accept the –credentials parameter.
Invoke-Command will not work as scripting is restricted on these servers.
What I’ve ended up with in $TopProcess is:
User Name CPU ID Description
--------- --- -- -----------
User73 25 68680 App89.exe
User73 25 68888 App57.exe
LOCAL SERVICE 2.5 63868 WmiPrvSE.exe
User48 0 66308 App38.exe
User48 0 62608 App54.exe
User73 25 68888 App57.exe
User73 25 68680 App89.exe
LOCAL SERVICE 2.5 63868 WmiPrvSE.exe
User48 0 59336 dwm.exe
User48 0 52528 App57.exe
User73 25 68888 App57.exe
User73 25 68680 App89.exe
User39 19.5 48792 App43.exe
User39 2.5 65996 App48.exe
LOCAL SERVICE 2.5 63868 WmiPrvSE.exe
but I need to list only the results that have a CPU over 15 and are listed three times but only to list each once and
$Result = $TopProcess | Where {$_.CPU -gt $Threshold} | Measure | Where {$_.Count -eq $NoRS}
returns nothing.

Use the Group-Object cmdlet instead of Measure to group your result. I think you only want to get the UserName property:
$Result = $TopProcess |
Where {$_.CPU -gt $Threshold} |
group 'User Name' |
Where Count -eq $NoRS |
select Name

Related

PowerShell Get-WinEvent Display only first line of Message property?

Getting acquinted with PowerShell, running into myriads of problems (lack of knowledge).
I'm trying to list myself Windows Security Log logged events by count, but I could also use a "friendly" description field which happens to be the first line of the "Message" Property. I can't figure out a way to extract only that.
Thus, I'm running the following to get an overview of events:
PS C:\TEST> Get-WinEvent -FilterHashtable #{logname="security"}| Group-Object id -NoElement | sort count
Count Name
----- ----
1 4724
1 4722
1 1102
1 4725
2 4718
2 6408
2 4739
2 1101
2 5038
2 4737
3 4717
4 6407
4 4731
10 4738
16 1100
19 4781
22 4904
22 4905
35 6406
38 5033
38 5024
39 4826
39 4608
39 4902
40 4735
113 4647
156 4616
239 5059
355 4688
551 4733
557 4732
605 4797
965 5061
977 5058
1647 4798
6364 4907
6759 4634
7000 4648
10950 4799
19407 4672
22049 4624
But what I want is to include the "Description/Message" Column to show what each event ID corresponds to. For example, for event ID the Message Property contains the following value(?):
An attempt was made to reset an account's password.
Subject:
Security ID: S-1-5-18
Account Name: [EDITED]
Account Domain: [EDITED]
Logon ID: 0x3E7
Target Account:
Security ID: [EDITED]
Account Name: Administrator
Account Domain: [EDITED]
Out of this entire Message I'd wish to extract only the following line:
An attempt was made to reset an account's password.
Thus getting back to my original view, ideally it would show the following:
Count Name Message
----- ---- ----
1 4724 An attempt was made to reset an account's password.
1 4722 A user account was enabled.
1 1102 The audit log was cleared.
(...)
Try this:
$Events = Get-WinEvent -FilterHashtable #{logname="security"} | Group-Object id
$Events | Select-Object Count,Name,#{Name='Message';Expression={ (($_.Group.Message | Select -First 1) -Split "`n")[0] }} | Sort-Object Count -Descending | Format-Table -Wrap
Works by removing the -NoElement parameter of Group-Object so that we get the Group result returned, which we can then retrieve the first line of the message property from.
We use Select-Object to add a calculated property to the result that contains the message.
Also using Format-Table -Wrap so the view of the final output doesn't truncate the first line if its long.
Example output:
Count Name Message
----- ---- -------
81 4798 A user's local group membership was enumerated.
13 5379 Credential Manager credentials were read.
5 5061 Cryptographic operation.
1 5058 Key file operation.

PowerShell script to calculate the memory usage per user

We have an environment of 240 VMs. Clients are using ICA/RDP connection to connect to these servers. Sometimes users are hogging the memory and causing the slowing and crash on that particular server.
I would like to have a PowerShell script to calculate the memory usage for each user connected to the server. I spent hours and hours searching and trying different scripts but was not successful.
Some scripts giving me the working sets value using Get-WmiObject Win32_Process and GetOwner(). but the calculation is not correct.
What I need is exactly the format that I can see in the users tab in Task Manager. The main information which I need is the memory usage, but it would be nice to have the disk and CPU usage per user as well.
Here is the code which i am using. When i run this script after a minute or two It returns an error which says $.GetOwner() can not be found and in another line it gives me the user name which utilizing the memory more than the others but the calculation is not correct when i compare it with TaskManager user's tab.
$h = #{}
get-wmiobject win32_process | foreach {
$u = $_.getowner().user;
if ( $u -ne $null)
{
if ( !$h.ContainsKey($u) )
{
$h.add( $u, $_.WS);
}
else
{
$h.item($u) = $h.item($u) + $_.WS;
}
}
}
$h.GetEnumerator() | sort value -desc
try this:
get-wmiobject win32_process |
select #{N='User';E={$_.getowner().user}}, WorkingSetSize |
group user |
select Name, #{N='CPU';E={($_.Group.WorkingSetSize | Measure-Object -Sum).Sum / 1Mb }}
gwmi win32_process |
select #{N='User';E={$_.getowner().user}},WorkingSetSize |
group User | select Name,#{N='RAM';E={[math]::Round(($_.Group.WorkingSetSize | Measure-Object -Sum).Sum/1MB) }} |
sort RAM -Descending | select -first 1 ;

Powershell Group Paramter - Count over 100 adds value to variable

I found the below article to help me group a list of IP addresses.
Using Powershell, how can i count the occurrence of each element in an array?
The command I am currently using is:
get-content c:\temp\temp3.txt | group
This would get the following output:
> Count Name Group
----- ---- -----
3 192.168.1.1 {192.168.1.1, 192.168.1.1, 192.168.1.1}
3 192.168.1.2 {192.168.1.2, 192.168.1.2, 192.168.1.2}
What command can I use to find all IP's with over a count of 5?
I imagine I would need to put my orignal command as a variable like below:
$groupedoutput get-content c:\temp\temp3.txt | group
Unsure where to go from there. Any help would be appreciated.
Thanks,
S
In full:
Get-Content -Path c:\temp\temp3.txt |
Group-Object -NoElement |
Where-Object { $_.Count -gt 5 } |
Select-Object -ExpandProperty Name
In short:
gc c:\temp\temp3.txt | group |? count -gt 5 |% Name
The -NoElement switch means the groups don't gather up all this stuff: {192.168.1.1, 192.168.1.1, 192.168.1.1} , it's not really necessary here but it saves memory if you aren't going to use the grouped items.

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.

Sorting by (custom) expression output

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