I am trying to find users that have been sending the most emails.
But in the end I only want to display the top 10 (or n number) of senders.
Is there a way to only show the top results using select-object or format-table
$Messages = Get-ExchangeServer * | where{$_.ServerRole -eq "HubTransport"} | %{get-messagetrackinglog -server $_.name -EventID "SEND" -Start (get-date -format G).AddDays(-1) -ResultSize unlimited}) 2>&1 | out-null
$messages | where{$_.sender -like "*#OurDomain.com*"} | select sender | group sender | sort count -Descending | ft count,name
Is there a way to make this only display the top results?
The only way I can think of would be storing them in a variable and outputting them in a for loop
Before the ft, add:
select -first 10
Replacing the 10 with how many you want.
So the full command would be:
$messages | where{$_.sender -like "*#OurDomain.com*"} | select sender | group sender | sort count -Descending | select -first 10 | ft count,name
This is asked a long time ago. But I got surprised by one thing, that you were using select and didn't look at this thing. Well in case you are thinking this is a rude answer - no it won't be. The point is you were this close to the solution. So few days back (by the way I don't know powershell much) I was asked this question and I had to display things only the first few. So the first thing I did was get-help *display* thinking that it would somehow show me something which would let me display some stuff. I was wrong, and realized I need to look for something. Then I look for the action words or the verbs. I checked get-Verb and then I could see the verbs that are relevant.
And I found select. It sounds reasonable, and then I opened help for select. get-help select -ShowWindow. And I checked the parameters and found this
-First <Int32>
Gets only the specified number of objects. Enter the number of objects to get.
Required? false
Position? named
Default value False
Accept pipeline input? False
Accept wildcard characters? false
And that's it. I don't know anything about power shell but I guess this can still be found with some workout like this.
For you, you knew that it would be select so you could have easily checked the parameters to solve it. In fact even the examples on how to do stuff is helpful. For example right after discovering First I got this example which made me clear about the syntax.
PS C:\>Get-Process | Sort-Object -Property WS | Select-Object -Last 5
Handles NPM(K) PM(K) WS(K) VS(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
2866 320 33432 45764 203 222.41 1292 svchost
577 17 23676 50516 265 50.58 4388 WINWORD
826 11 75448 76712 188 19.77 3780 Ps
1367 14 73152 88736 216 61.69 676 Ps
1612 44 66080 92780 380 900.59 6132 INFOPATH
Yes this can be first as well and I did that and got the result.
PS C:\WINDOWS\system32> Get-Process | Sort-Object -Property WS | Select-Object -First 5
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
0 0 60 8 0 0 Idle
841 39 22988 8 0.69 2540 3 SystemSettings
538 38 17900 36 0.97 12636 3 WinStore.App
452 29 16568 44 0.81 25724 3 Video.UI
181 11 1800 832 0.08 6544 0 GoogleCrashHandler
Note: The previous answer is awesome and showed everything that the OP needed. I am just showing my way of solving the same thing.
Related
I want to output the last entry of Get-Hotfix in PowerShell. How does it work?
Example:
Source Description HotFixID InstalledBy InstalledOn
------ ----------- -------- ----------- -----------
DESKTOP-FU... Update KB5010472 NT-AUTORITÄT\SYSTEM 15.03.2022 00:00:00
DESKTOP-FU... Update KB5003791 06.10.2021 00:00:00
DESKTOP-FU... Security Update KB5011487 NT-AUTORITÄT\SYSTEM 14.03.2022 00:00:00
DESKTOP-FU... Update KB5007273 NT-AUTORITÄT\SYSTEM 02.01.2022 00:00:00
DESKTOP-FU... Security Update KB5011352 NT-AUTORITÄT\SYSTEM 09.02.2022 00:00:00
DESKTOP-FU... Security Update KB5005699 06.10.2021 00:00:00
I want to output the KB5005699 update to the console.
You can use Select-Object with the -Last 1 parameter to get the last object and -ExpandProperty HotFixID to get the Value of the HotFixID property:
Get-HotFix | Select-Object -Last 1 -ExpandProperty HotFixID
Another alternative would be to get the last object by the -1 index and use dot notation .HotFixID to get the Value:
(Get-HotFix)[-1].HotFixID
This command works, logfolder contains several log files, select-string will search on each file and look for the -pattern 'update'
get-childitem -recurse C:\logfolder -file | select-string -pattern "update"
But this other line won't work, it won't return any results
get-eventlog -logname system -entrytype error | select-string -pattern "terminated"
I am 100% positive that there is an event with the string "terminated", maybe I am missing some concepts here.
select-string converts the input object to a string. Unfortunately with get-eventlog this isn't very helpful. By the way, get-eventlog has been replaced by get-winevent.
get-eventlog -logname system -entrytype error | select -first 1
Index Time EntryType Source InstanceID Message
----- ---- --------- ------ ---------- -------
63255 Aug 31 07:44 Error Microsoft-Windows... 1129 The processing of Group Policy failed because o...
get-eventlog -logname system -entrytype error | select -first 1 | % { "$_" }
System.Diagnostics.EventLogEntry
get-eventlog -logname system -entrytype error | select -first 1 | select-string log
System.Diagnostics.EventLogEntry
get-eventlog -logname system -entrytype error | select -first 1 |
where message -match processing
Index Time EntryType Source InstanceID Message
----- ---- --------- ------ ---------- -------
63255 Aug 31 07:44 Error Microsoft-Windows... 1129 The processing of Group Policy failed because of lack of network connectivity to a domain controller. This may be a transient cond...
get-winevent #{logname='system';level=2} -maxevents 1 |
? message -match processing | ft -GroupBy logname
ProviderName: System
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
8/31/2021 7:44:27 AM 1129 Error The processing of Group Policy failed because of lack of network connectivity to a domain controller. This may be a transient condition. A success...
I want to be able to to output to a log file the top CPU consumers every 5 seconds. That way I will be able to see who uses the most of the cpu during my tests.
I have found this answer very common:
$cpu = Get-Counter -ComputerName localhost "\Process(*)\% Processor Time" `
| Select-Object -ExpandProperty countersamples `
| where {$_.InstanceName -ne 'idle' } `
| where {$_.InstanceName -ne '_total' }`
| Select-Object -Property instancename, cookedvalue `
| Sort-Object -Property cookedvalue -Descending `
| Select-Object -First 5 `
| ft #{L='Date';E={Get-Date}}, InstanceName, #{L='CPU';E={(($_.Cookedvalue/100)/$NumberOfLogicalProcessors).toString('P')}} -HideTableHeaders `
| Format-Table -Auto | Out-String
I have 2 issues with it:
Sometimes I get:
Get-Counter : The data in one of the performance counter samples is not valid. View the Status property for each PerformanceCounterSample object to make sure it contains valid data.
I would like to get the full process name, and not
java 25%
idea64 0.8%
...
I'll try to answer your two questions at once with following script:
Get-Counter "\Process(*)\% Processor Time" -ErrorAction SilentlyContinue `
| select -ExpandProperty CounterSamples `
| where {$_.Status -eq 0 -and $_.instancename -notin "_total", "idle"} `
| sort CookedValue -Descending `
| select TimeStamp,
#{N="Name";E={
$friendlyName = $_.InstanceName
try {
$procId = [System.Diagnostics.Process]::GetProcessesByName($_.InstanceName)[0].Id
$proc = Get-WmiObject -Query "SELECT ProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId=$procId"
$procPath = ($proc | where { $_.ExecutablePath } | select -First 1).ExecutablePath
$friendlyName = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($procPath).FileDescription
} catch { }
$friendlyName
}},
#{N="CPU";E={($_.CookedValue/100/$env:NUMBER_OF_PROCESSORS).ToString("P")}} -First 5 `
| ft -a -HideTableHeaders
This results in following table:
24.07.2016 21:00:53 Microsoft Edge Content Process 9,68%
24.07.2016 21:00:53 system 0,77%
24.07.2016 21:00:53 Microsoft Edge 0,39%
24.07.2016 21:00:53 runtimebroker 0,39%
24.07.2016 21:00:53 Host Process for Windows Services 0,39%
As specified, you sometimes get:
Get-Counter : The data in one of the performance counter samples is
not valid. View the Status property for each PerformanceCounterSample
object to make sure it contains valid data.
This is related to process management in windows environment. While you execute query, some processes may appear, some of them may disappear (i.e. wmiprvse process responsible for executing wmi queries). Some processes may require more permissions you have. This all leads to error when obtaining process information. It can be safely skipped using -ErrorAction SilentlyContinue switch and filtered with Status -eq 0 expression.
You also want to see more friendly process name. I don't know if there is better way of getting that name than from executable itself using GetVersionInfo method. If such information is available FileDescription property stores that value. If it's not available then non-friendly process name is used.
you get output something like this
Name CPU CPUPercent Description
---- --- ---------- -----------
chrome 10.4988673 8.79 Google Chrome
powershell_ise 6.5364419 7.16 Windows PowerShell ISE
chrome 38.0174437 4.88 Google Chrome
chrome 26.2549683 4.87 Google Chrome
chrome 16.9417086 3.16 Google Chrome
cavwp 10.2648658 2.67 COMODO Internet Security
chrome 13.1820845 2.44 Google Chrome
chrome 675.016327 2.02 Google Chrome
7.9.7_42331 1037.1570484 1.51 BitTorrent
chrome 340.8777851 1.02 Google Chrome
With
$CPUPercent = #{
Name = 'CPUPercent'
Expression = {
$TotalSec = (New-TimeSpan -Start $_.StartTime).TotalSeconds
[Math]::Round( ($_.CPU * 100 / $TotalSec), 2)
}
}
Get-Process -ComputerName $env:computername |
Select-Object -Property Name, CPU, $CPUPercent, Description |
Sort-Object -Property CPUPercent -Descending |
Select-Object -First 10 |format-table -autosize | out-file c:\pro.log
credit :http://powershell.com/cs/blogs/tips/archive/2013/04/16/documenting-cpu-load-for-running-processes.aspx
Get-Process -ComputerName $env:computername for remote computers you can have in csv
Import-CSV c:\"computers.csv" | % {
$Server = $_.ServerName
$alivetest = Test-Path "\\$Server\c$\"
If ($alivetest -eq "True")
{Get-Process -ComputerName $server |
Select-Object -Property Name, CPU, $CPUPercent, Description |
Sort-Object -Property CPUPercent -Descending |
Select-Object -First 10 |format-table -autosize | out-file c:\pro.log}
}}
So I managed to check if a sevice is running with sc query "ServiceName" | find "RUNNING" or net start | find "Service Name", or in SQL Server using xp_servicecontrol. Is there any way to see the uptime of a service? How can I see the uptime of a service?
As long as your service has it's own process name, this should work.
PowerShell_v4> (Get-Process lync).StartTime
Friday, October 17, 2014 11:46:04
If you're running under svchost.exe, i think you need to grab that from Event Log.
PowerShell_v4> (Get-WinEvent -LogName System | ? Message -match 'DHCPv6 client service is started' | select -First 1).TimeCreated
Friday, October 17, 2014 10:10:56
For Uptime, just compute time diff.
$Start = (Get-Process Outlook).StartTime
$Now = Get-Date
$Now - $Start | Format-Table Days, Hours, Minutes, Seconds -AutoSize
Days Hours Minutes Seconds
---- ----- ------- -------
0 0 2 8
or as a one-liner:
(Get-Date) - (Get-Process Outlook).StartTime | Format-Table Days, Hours, Minutes, Seconds -AutoSize
Days Hours Minutes Seconds
---- ----- ------- -------
0 0 2 8
There doesn't seem to be any simple explanations on how to get CPU Percentage for a process in Powershell. I've googled it and searched here and I'm not seeing anything definitive. Can somebody explain in layman terms how to get CPU Percentage for a process? Thanks!
Here's something to get you started ;)
$id4u = gps | ? {$_.id -eq 412}
function get_cpu_percentage {
# Do something cool here
}
get_cpu_percentage $id4u
Using WMI:
get-wmiobject Win32_PerfFormattedData_PerfProc_Process | ? { $_.name -eq 'powershell' } | select name, PercentProcessorTime
Function:
function get_cpu_percentage ($id )
{
(get-wmiobject Win32_PerfFormattedData_PerfProc_Process | ? { $_.idprocess -eq $id.id }).PercentProcessorTime
}
$id4u = gps | ? {$_.id -eq 412}
get_cpu_percentage -id $id4u
How about this?
gps powershell_ise | Select CPU
Mind you, this is a scriptProperty and won't show anything for remote systems. This is known.
get-counter provides information on system performance. You can obtain information on single processes as well. There is more about it here: http://social.technet.microsoft.com/Forums/lv/winserverpowershell/thread/8d7502d4-9e67-43f7-94da-01755b719cf8 and here http://blogs.technet.com/b/heyscriptingguy/archive/2010/02/16/hey-scripting-guy-february-16-2010a.aspx
I'm not sure if this is what you are looking for, but here is one possibility using the process name and get-counter.
Note: if you have more than 1 processor i believe you should divide the result by the number of processors. You can get this value using:
$env:NUMBER_OF_PROCESSORS
function get_cpu_percentage {
param([string[]]$myProc)
return (get-counter -Counter "\Process($myProc)\% processor time" -SampleInterval 5 -MaxSamples 5 | select -ExpandProperty countersamples | select -ExpandProperty cookedvalue | Measure-Object -Average).average
}
get_cpu_percentage ("powershell")
or using proc id and gps:
Note: I believe the value returned by get-process is the CPU seconds used by the process since start up. It is not the cpu percentage used.
function get_cpu_since_start{
param ([system.object]$p)
$id4ucpu = $p | select-object CPU
return $id4ucpu.CPU
}
get_cpu_since_start (gps | ? {$_.id -eq 412})