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})
Related
I'm writing an PowerShell script to collect some data of a computer. I'm almost done, but I don't know how to get size of all the disks on the computer. I know how to do it with a couple of If statements, but I want it to automatically detect the drives, not that I have to write a new If statement if a new disk is attached. The output I want is as follows: "A:,250GB". The "A:," bit works, but not the disk size bit.
This is the code I used and tweaked, but to no avail:
$Drives = Get-WmiObject Win32_logicaldisk| ?{$_.DriveType -eq 3} | ForEach-Object {$_.name}
ForEach ($Drivename in $Drives) {
$Drivenames = Get-WMIObject -Query "Select * From win32_logicaldisk Where DriveType = '3'" -computer localhost | Select-Object DeviceID
$Drive = [Math]::Round($Drivenames.Size / 1GB)
"$Drivenames,", $Drive | Out-File "C:\HDS\HDS_DRIVES.csv" -Append
}
In addition, [Math]::Round($Drivenames.Size / 1GB) throws me an error:
Method invocation failed because [System.Object[]] does not contain a method named 'op_Division'"
You can use Calculated Property with Select-Object to make it much more simple:
Get-WmiObject Win32_logicaldisk| ? {$_.DriveType -eq 3} |
Select-Object #{N="DeviceId";E={$_.DeviceId}},`
#{N="VolumeName";E={$_.VolumeName}},`
#{N="Size";E={[Math]::Round($_.Size / 1GB)}} |
Out-File "C:\HDS\HDS_DRIVES.csv" -Append
Note that you don't need to Invoke Get-WmiObject Twice like in your example.
Why it doesn't work?
The issue is that $Drivenames contains only DeviceID (as you used Select-Object to get only that property). Therefore you're getting an error where trying to round it (as rounding nothing is not supposed to work).
How to fix it?
You have to add Size and then access it using .PropertyName:
$DriveInfo = Get-WMIObject -Query "Select * From win32_logicaldisk Where DriveType = '3'" -computer localhost | Select-Object DeviceID, Size
$DriveInfo | ForEach-Object {
$DriveSize = [Math]::Round($_.Size / 1GB)
"$($_.DeviceID),$DriveSize" | Out-File "C:\HDS\HDS_DRIVES.csv" -Append
}
How can I make it more elegant
Also, take a look at #Avshalom's answer which uses calculated property.
In task manager we can see memory ( private working set ).
My question is How to get memory ( private working set ) of a process in powershell? See image
(https://i.stack.imgur.com/JQInb.jpg)
One way to do it is this:
(Get-Counter "\Process(*)\Working Set - Private").CounterSamples
EDIT: Convert value to MB:
The following takes the output of Get-Counter and sorts the processes alphabetically, then creates a table with the Working Set value converted to MB:
(Get-Counter "\Process(*)\Working Set - Private").CounterSamples |
Sort-Object InstanceName |
Format-Table InstanceName, #{Label="PrivateWorkingSet"; Expression={$_.CookedValue / 1MB}} -AutoSize
Why this not work please ?
get-process -Name iexplore | select name, #{Name="Private Working Set"; Expression = {(Get-Counter "\Process(*)\Working Set - Private").CounterSamples | Sort-Object InstanceName | Format-Table InstanceName, #{Label="PrivateWorkingSet"; Expression={$_.CookedValue / 1MB}} -AutoSize}}
this should work
get-process -Name iexplore |
select name, #{Name = "Private Working Set"; Expression = {
$ProcessID = $_.ID; [math]::Round((gwmi Win32_PerfFormattedData_PerfProc_Process |
? {$_.IDprocess -eq $ProcessID }).WorkingSetPrivate / 1mb, 0)
}
}
How do I make it that no system services are enumerated? I would like to have both the system process as well as all other system services such as svchost not in the list.
Get-Process | Sort-Object CPU -desc | Select-Object -first 3 | Format-Table CPU,ProcessName,Id -hidetableheader
I like the other answer, but here's another possibility that doesn't need admin rights, although it might not be fool proof:
Most system services run within a process named svchost so you could simply exclude these processes with Where-Object:
Get-Process | Where-Object {$_.name -ne 'svchost'} | Sort-Object CPU -desc | Select-Object -first 3 | Format-Table CPU,ProcessName,Id -hidetableheader
You may need to be in Admin mode.
Get-Process -IncludeUserName | where {$_.UserName -notlike "NT AUTHORITY\SYSTEM"} | Sort-Object CPU -desc | Select-Object -first 3 | Format-Table CPU,ProcessName,Id -hidetableheader
Is this what you were asking for?
I like the other answers for their simplicity, however you can use the WMI class Win32_Process to retrieve a list of process and the method .GetOwner() to get the owner of the process.
As system processes do not show an owner we can easily filter on process that do have an owner, showing most non-system processes (I say most because svchost shows up under my account every now and then).
# Get all processes
$processes = Get-WMIObject -Class Win32_Process
foreach($process in $processes)
{
try
{
$processOwner = $process.GetOwner()
}
catch
{
continue
}
if ($processOwner.User -ne $null)
{
$processData = Get-Process -Id $process.ProcessId
$process | Select-Object -Property #{n='CPU';e={$processData.CPU}},Name,ID | Sort-Object -Property CPU
}
}
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}
}}
Is there a better way to list counter properties for a particular process:
$pids = get-counter -listset process | get-counter -maxsamples 1 | select -expandproperty countersamples | where {$_.path -like "w3wp"} | select cookedvalue | ForEach {$_.cookedvalue}
You can use WMI class "Win32_PerfFormattedData_PerfProc_Process" to do this as well:
Get-WmiObject -Class Win32_PerfFormattedData_PerfProc_Process -Filter "Name='w3wp'"
This will give you the performance counter data pertaining to w3wp processes.