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}
}}
Related
I can get list the processes but how would I get them to show by highest usage instead of alphabetically?
Wmic path win32_performatteddata_perfproc_process get Name,PercentProcessorTime
From powershell you don't need to make direct calls to wmic, Get-CimInstance is meant to easily query all instances of WMI and CIM classes and output objects which are easy to manipulate. Sorting objects in PowerShell can be done with Sort-Object.
Get-CimInstance Win32_PerfFormattedData_PerfProc_Process |
Sort-Object PercentPrivilegedTime -Descending |
Select-Object Name, PercentProcessorTime
You could even go one step further and group the objects by their name with the help of Group-Object:
Get-CimInstance Win32_PerfFormattedData_PerfProc_Process |
Group-Object { $_.Name -replace '#\d+$' } | ForEach-Object {
[pscustomobject]#{
Instances = $_.Count
Name = $_.Name
PercentProcessorTime = [Linq.Enumerable]::Sum([int[]] $_.Group.PercentProcessorTime)
}
} | Sort-Object PercentProcessorTime -Descending
Need to use a command in windows powershell to get top 10 process in %CPU utilization. It should return me process name, %CPU and used memory order by %CPU, like task manager does.
How can I get this list in powershell?
I find this one
Get-Counter "\Process(*)\% Processor Time" -ErrorAction SilentlyContinue `
| select -ExpandProperty CounterSamples `
| where {$_.Status -eq 0 -and $_.instancename -notin "_total", "idle"} `
| sort CookedValue -Descending `
| select #{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 10 `
| ft -a -HideTableHeaders
But, it is not working when insert memory info in Kbytes
How do I properly use $_ in out-file? Here's my code:
get-content computers.txt |
Where {$_ -AND (Test-Connection $_ -Quiet)} |
foreach { Get-Hotfix -computername $_ } |
Select CSName,Description,HotFixID,InstalledBy,InstalledOn |
convertto-csv | out-file "C:\$_.csv"
I'm trying to execute a get-hotfix for all the computers listed in the text file then I want them to be exported to CSV with the computer name as the filename.
You need one pipeline to process the computers.txt files, and a nested one inside the foreach to process the list of hotfixes for each computer:
get-content .\computers.txt |
Where {$_ -AND (Test-Connection $_ -Quiet)} |
foreach {
Get-Hotfix -computername $_ |
Select CSName,Description,HotFixID,InstalledBy,InstalledOn |
convertto-csv | out-file "C:\$_.csv"
}
Edit: Changed computers.txt to .\computers.txt, as this is required for local paths in powershell
i can see with this:
get-content .\computers.txt | Where {$_ -AND (Test-Connection $_ -Quiet)} | foreach{ Get-Hotfix -id KB4012212 -computername $_ | Select CSName,Description,HotFixID,InstalledBy,InstalledOn | convertto-csv | out-file "C:\$_.csv" }
i can see only in which PC is the fix (KB4012212) installed.
it's possible to see the following
CSNAME Fix(Inst/NotInst)
PC1 FIxInstalled
PC2 FixNotinstalled
PC3 FixnotInstalled
..
..
etc
I monkeyed with this for a while and nothing I found on-line worked until I used this combo.
I used the method is this thread but it was SO slow and I wanted to learn more about using jobs so this is what ended up working for me on Windows 7 PS Ver 4.
All other options were either too slow or did not return data from the remote system.
$VMs = get-content C:\WinVms.txt #Generate your hostnames list however you deem best.
foreach ($vm in $vms)
{
Write-Host "Attempting to get hotfixes on:" $vm
invoke-command -computername $vm -ScriptBlock {start-job -scriptblock {(get-hotfix | sort installedon)[-1]} | wait-job | receive-job} -AsJob
}
start-sleep 60 # give it a minute to complete
get-job | ? { $_.state -eq "Completed"} | receive-job -keep | export-csv c:\temp\win-patch.csv
you can check your failures too like this:
get-job | ? { $_.state -eq "Failed"}
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 have a working script that is able to pull a report of Windows Application, Security, Setup and System logs that displays only the critical and error events in the past 30 days. However, I would also really like the script to count the number of times each reported critical or error event occurred in the past 30 days. Here's the working command:
Get-EventLog Application -ComputerName $server -After $starttime |
? { $_.entryType -Match "Error" -and "Critical" } |
Sort-Object EventID -Unique |
Select-Object TimeGenerated,EventID,Source,Message |
ft -AutoSize -Wrap |
Out-File $file -Append
And here is an example of the output in the text file:
TimeGenerated EventID Source Message
------------- ------- ------ -------
7/8/2016 1:23:20 PM 0 SQL Server Report Service Service cannot be started. Microsoft.ReportingS
ervices.Diagnostics.Utilities.InternalCatalogEx
ception: An internal error occurred on the repo
rt server. See the error log for more details.
at Microsoft.ReportingServices.Library.Nativ
e.GetSid(String name, Int32& length)
at Microsoft.ReportingServices.Library.Nativ
e.NameToSid(String name)
at Microsoft.ReportingServices.Library.Servi
ceAppDomainController.StartRPCServer(Boolean fi
rstTime)
at Microsoft.ReportingServices.Library.Servi
ceAppDomainController.Start(Boolean firstTime)
at Microsoft.ReportingServices.NTService.Rep
ortService.OnStart(String[] args)
at System.ServiceProcess.ServiceBase.Service
QueuedMainCallback(Object state)
7/8/2016 1:23:20 PM 121 Report Server Windows Service (MSSQLSERVER) The Remote Procedure Call (RPC) service failed
to start.
It would be great to have another column in the results that displays the occurrences of each EventID in the specified time period.
You could do it like so (line 3 & 4 are new and Count in Select-Object)
Technically you could also remove the -Unique from Sort-Object as after grouping them and passing through only the first item of the group is more or less the same.
Get-EventLog Application -ComputerName $server -After $starttime |
? { $_.entryType -Match "Error" -and "Critical" } |
Group-Object -Property EventID |
% { $_.Group[0] | Add-Member -PassThru -NotePropertyName Count -NotePropertyValue $_.Count } |
Sort-Object EventID -Unique |
Select-Object Count, TimeGenerated, EventID, Source, Message |
ft -AutoSize -Wrap |
Out-File $file -Append