Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get list of processes same as in task manager in powershell console

Tags:

powershell

I'm trying to get same list of process as in Task Manager in Windows 2008 server

enter image description here

I can't get some values even from WMI objects, such as CPU time, UAC Virtualisation, User Name (e.g. process owner), User Objects, CPU Usage, all memory columns, Handles and threads.

Here is some piece of code I made trying to make it work

Clear-Host

$Processes = Get-Process
foreach ($Process in $Processes) {
$PIDN = $Process.Id
$NAMEProcess = $Process.Name
$NAME  = (Get-WmiObject Win32_Process | where {$_.Name -match $NAMEProcess}).Name
$PATH  = (Get-WmiObject Win32_Process | where {$_.Name -match $NAMEProcess}).Path
$CMD   = (Get-WmiObject Win32_Process | where {$_.Name -match $NAMEProcess}).CommandLine

$OWNER = (Get-WmiObject win32_process | where {$_.Name -match $NAMEProcess}).getowner().user
$SESSIONID = (Get-WmiObject Win32_Process | where {$_.Name -match $NAMEProcess}).SessionId
$CPU = $Process.CPU
$WORKINGSET64 = $Process.WorkingSet64
$PEAKWORKINGSET64 = $Process.PeakWorkingSet64
$THREADS = $Process.Threads.Count
$HANDLES = $Process.Handles
$DESCRIPTION = $Process.Description

$obj = new-object psobject
$obj | add-member noteproperty "PID" ($PIDN)
$obj | add-member noteproperty "NAME" ($NAME)
$obj | add-member noteproperty "OWNER" ($OWNER)
$obj | add-member noteproperty "PATH" ($PATH)
$obj | add-member noteproperty "Command Line" ($CMD)
$obj | Add-Member noteproperty "SessionID" ($SESSIONID)
$obj | Add-Member noteproperty "CPU" ($CPU)
$obj | Add-Member noteproperty "WorkingSet64" ($WORKINGSET64)
$obj | Add-Member noteproperty "Peak Working Set64" ($PEAKWORKINGSET64)
$obj | Add-Member noteproperty "HANDLES" ($HANDLES)
$obj | Add-Member noteproperty "THREADS" ($THREADS)
$obj | Add-Member noteproperty "DESCRIPTION" ($DESCRIPTION)

write-output $obj | Format-Table
# $obj | Format-Table $PIDN, $NAME
}

Also couldn't make it to output in proper table. Could you please help me with that? Thank you.

like image 394
Senator14 Avatar asked Mar 12 '23 19:03

Senator14


2 Answers

did you take a look at performance counters?

Get-Counter "\Process(*)\Working Set - Private"
Get-Counter "\Process(*)\Handle Count"

For further documentation on Get-Counter use

get-help get-counter -Full

or goto: https://technet.microsoft.com/en-us/library/hh849685.aspx

like image 118
Nickolai Nielsen Avatar answered Apr 07 '23 18:04

Nickolai Nielsen


First, you need to be using the data from a single use of Get-WMIObject (gwmi).

When you make multiple calls using GWMI, you're effectively taking another snapshot of data every time and using a different sample for each property. You're going to end up with a table of data befitting of a cubist Picasso painting... it won't align or represent the whole list. It also takes a lot more time to recapture the process list over and over then grab only a single property from each different list, so its worth it to take the time to modify a single set of data, especially if you end up repurposing your script in a massive remote operations script that compiles a database of tasks.

There are different ways to grab only the properties you want in the form of PS Custom Objects. I use hash tables to make the code short and easy, and to make the code efficient-- You already executed the verbage you would have done for a hash table, in the form of:

$CPU = $Process.CPU
$WORKINGSET64 = $Process.WorkingSet64
$PEAKWORKINGSET64 = $Process.PeakWorkingSet64 
$THREADS = $Process.Threads.Count
$HANDLES = $Process.Handles
$DESCRIPTION = $Process.Description

So instead, just do

$taskProps = @{
  'SID'=$task.SessionId
  'Name'=$task.ProcessName
  'PID'=$task.ProcessId
  # add more properties here.
}

And instead of creating a blank custom object, and then 'writing' to it multiple times with

$obj = new-object psobject
$obj | add-member noteproperty "PID" ($PIDN)
$obj | add-member noteproperty "NAME" ($NAME)
$obj | add-member noteproperty "OWNER" ($OWNER)
$obj | add-member noteproperty "PATH" ($PATH)
$obj | add-member noteproperty "Command Line" ($CMD)
$obj | Add-Member noteproperty "SessionID" ($SESSIONID)
$obj | Add-Member noteproperty "CPU" ($CPU)
$obj | Add-Member noteproperty "WorkingSet64" ($WORKINGSET64)
$obj | Add-Member noteproperty "Peak Working Set64" ($PEAKWORKINGSET64)
$obj | Add-Member noteproperty "HANDLES" ($HANDLES)
$obj | Add-Member noteproperty "THREADS" ($THREADS)
$obj | Add-Member noteproperty "DESCRIPTION" ($DESCRIPTION)

You can package the property hashtable and create in a single shot, the custom object at the end:

$taskObject = New-Object -TypeName PSObject -Property $taskProps

Then store it in an arraylist with

$taskList += $taskObject

You can see my example here:

# Generates a collection of "System.Management.ManagementObject#root\cimv2\Win32_Process"
# Only do this once. Every time gwmi is used, it makes another RPC call if used remotely.
# If you do multiple GWMIs you'll be working with differing data samples.
$taskSnapshot = Get-WMIObject -ComputerName [machine name] -Class Win32_Process

# Initialize, nullify, and declare your list as an empty ArrayList.
$taskList = @()

# Begin formatting in prep of Format-Table or similar usage
# This is where you'd define each property you want to see, manipulation, etc.
foreach ($task in $taskSnapshot){

# Create the hash table which will temporarily store all information for each task naming/assigning only
# properties you want to display.
    $taskProps = @{
        'SID'=$task.SessionId
        'Name'=$task.ProcessName
        'PID'=$task.ProcessId
             # additional properties here.
    }

# "Packages" the new custom object in a variable that stores the object
    $taskObject = New-Object -TypeName PSObject -Property $taskProps

# append (addition) operation on formerly defined arraylist to store
# the packaged object to an arraylist.
    $taskList += $taskObject
}

# Displays the list of task "objects" in a table, other formatting options are available online.
$taskList | Format-Table -AutoSize

Using Format Commands to Change Output View:

https://technet.microsoft.com/en-us/library/dd347677.aspx

Windows PowerShell: The Many Ways to a Custom Object:

https://technet.microsoft.com/en-us/magazine/hh750381.aspx

I would also recommend checking out Out-GridView as it will create a GUI table of the data which you can resize and easily click around in.

The important part is to use GWMI once. It would be better practice to capture the raw information in a single variable, then perform your Select-String/where/if/manipulation and formatting operations on the dataset within your foreach statement.

Here's the clean copy of the example, with my select aliases.

$taskSnapshot = gwmi -cn localhost -class win32_process
$taskList = @()
foreach ($task in $taskSnapshot){
    $taskProps = @{
        'SID'=$task.SessionId
        'Name'=$task.ProcessName
        'PID'=$task.ProcessId
    }
    $taskObject = New-Object -TypeName PSObject -Property $taskProps
    $taskList += $taskObject
}

$taskList | Out-GridView

Another thing someone mentioned is the min/max working set properties...

You can look at all the properties of Win32_Process by doing

Get-WMIObject -Class Win32_Process | Get-Member

or

gwmi -cl win32_process | gm
like image 34
Chris Kuperstein Avatar answered Apr 07 '23 19:04

Chris Kuperstein