Montag, 28. Dezember 2009

Compare-Object & get-wmiobject win32_process does it right

Hello
the fasted way to have lots of processes with the same ProcessName is use Chrome, which opens for each tab its own process and uses a few of it's own. I heard rumours that firefox will use seperate processes in future versions too. But here I'm not going to start any process vs. thread discussion. Here I will play with processes with the same name. You can just start Notepad for this purpose.

get-process | ? {$_.Name -eq 'Notepad' } | Kill            


Notepad
Notepad
notepad
notepad

$gp_a = get-process notepad
$gwmip_a = get-wmiobject win32_process | ? {$_.Name -eq 'notepad.exe'}


The code above just ensures, that there are 4 instances of notepad running.
Next close one of the first 3 instances and take fresh snapshots.

$gp_b = get-process notepad             
$gwmip_b = get-wmiobject win32_process | ? {$_.Name -eq 'notepad.exe'}


Let's look at them:

$gp_a            


Initially there where 4 processes:


PS C:\Var\bin> $gp_a

Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
69 3 992 7612 72 1492 notepad
69 3 976 4220 55 2272 notepad
68 3 972 4096 55 3368 notepad
13 1 284 60 2 5480 notepad



$gp_b


In second snapshot there are 3 processes (PID 2272 got killed)


PS C:\Var\bin> $gp_b

Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
72 3 1012 7852 59 1492 notepad
72 3 1012 7800 59 3368 notepad
72 3 1020 7960 59 5480 notepad



Compare-Object $gp_a $gp_b |             
Where-object {$_.SideIndicator -ne '=='} |
Select -ExpandProperty InputObject


Trying to use Compare-Object on the results of get-Process, as recommended in http://technet.microsoft.com/en-us/library/ee156812.aspx I get a wrong result


PS C:\Var\bin> Compare-Object $gp_a $gp_b |
Where-object {$_.SideIndicator -ne '=='} |
Select -ExpandProperty InputObject


Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
13 1 284 60 2 5480 notepad



(Compare-Object $gwmip_a $gwmip_b |             
Where-object {$_.SideIndicator -ne '=='}).Inputobject |
Select ProcessId, Name


while good old WMI gives the correct answer


PS C:\Var\bin> (Compare-Object $gwmip_a $gwmip_b |
Where-object {$_.SideIndicator -ne '=='}).Inputobject |
Select ProcessId, Name


ProcessId Name
--------- ----
2272 notepad.exe




The documentation of Compare-Object contains the funny sentense:
The result of the comparison indicates whether a property value appeared only in the object from the Reference set (indic
ated by the <= symbol), only in the object from the Difference set (indicated by the => symbol) or, if the IncludeEqual p
arameter is specified, in both objects (indicated by the == symbol).


Does it chose a property by incident and in the case of Get-Process, does it use ProcessName instead of Id ?


Is there someone who can tell more about the logic Compare-Object uses to determine whether two objects are the same.

Kommentare:

  1. Just found, that I get the expected result, when I use
    Compare-Object $gp_a $gp_b -prop ID

    It just seems to be a matter of wrong default.

    AntwortenLöschen
  2. It looks like it is defaulting to the value of ToString().

    PS > $dates = 1..10 | %{get-date; Start-Sleep 2}
    PS > $dates1 = $dates
    PS > $dates2 = $dates[0..4+6..9]
    PS > Compare-Object $dates1 $dates2

    InputObject SideIndicator
    ----------- -------------
    12/28/2009 9:45:08 AM <=
    PS > $dates1[5].ToString()
    12/28/2009 9:45:08 AM

    AntwortenLöschen