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.

Sonntag, 27. Dezember 2009

Small Get-Process Puzzle

Hello PowerShell folks,

here I have a small puzzle for you. Please start only one instance of PowerShell odr PowerShell_ISE and run the following script.

$p1 = get-process powershell*             
$p2 = get-process powershell*

$p1
$p2

$p1 -eq $p2

Compare-Object $p1 $p2 -IncludeEqual


This time I'm not confuesed, that Compare-Object tells that both processes are equal. This time I wonder why $p1 is not equal To $p2.

When you invoke $p1 a number of times, you will see that the value CPU(s) increases. My natural expectation here is same PID same process.

Is this a PowerShell or a .NET issue ?
Do I better keep using WMI?

I get the rather strange feeling 'The more I learn, the less I know'.

Bernd

Freitag, 25. Dezember 2009

Compare-Object works different

Sorry Mr. Snover. I don't grock the way Compare-Object is intented to work.

Or I'm just misinterpreting the examples in http://technet.microsoft.com/en-us/library/ee156812.aspx for a second time.

The first time I was led to think, that Compare-Object is a good basis to produce diffs of text files. It hardly is capable to tell whether they are equal or different.

This time I thought it adequat to determine the processes which where started between two calls of GET-Process.
Well it correctly tells the name of the processes involved, but having a lot of chrome processes
(Chrome Plus to be precise) I do not get the PID of correct chrome process stopped.
And for me a process is it primary it's PID and not it's name.

With a little work around I get Compare-Object to work here as expected.


function Get-ProcessProperty ( )            
{
[CmdletBinding()]
PARAM(
$process = '*',
$timestamp = "{0:T}" -f (Get-Date)
)

$hash1 = @{}
Get-Process -Name $process | % {
$hash2 = @{}
#$hash2['Time'] = $timestamp
$hash2['Name'] = $_.name
#$hash2['CPU'] = $_.CPU
#$hash2['PM'] = "{0,3:f0}" -f ( $_.PM / 1MB )
#$hash2['NPM'] = "{0,4:f1}" -f ( $_.NPM / 1KB )
#... add further properties above
$hash1[($_.Id)] = $hash2
}
$hash1
}


$psold = get-ProcessProperty

(
'\PhysicalDisk(_total)\Current Disk Queue Length',
'\PhysicalDisk(_total)\Disk Transfers/sec'
) | Get-Counter -cont -sample 1 |% {
$timestamp = "{0:T}" -f $_.Timestamp

$diskQueue = ($_.CounterSamples[0]).CookedValue
$transfer = ($_.CounterSamples[1]).CookedValue

$msg = "{0} {1,4:f0} {2,4:f0}" -f $timestamp, $diskQueue, $transfer

$psnew = get-ProcessProperty

# Show Processes that started or stopped
Compare-Object @($psold.keys) @($psnew.keys) |%{
$Id = $_.inputObject
if ($_.Sideindicator -eq '=>')
{
$Name = ($psnew[$id]).Name
"$timestamp Start $Id $Name"
}
if ($_.Sideindicator -eq '<=')
{
$Name = ($psold[$id]).Name
"$timestamp $Id $Name stop"
}
}
$psold = $psnew

# the following code is special to a problem on my Windows 7 installation
# my problem is, when Current Disk Queue Length > 0, but Disk Transfers/sec 0
if ($diskQueue -gt 0 -and $transfer -eq 0)
{
$msg
}
}

Using PowerShell to log Start and Stop of Processes and watch some counters

Merry Christmas everyone.

Today I show a little of PowerShell script, which logs when processes start and when they end.

I wrote it, because I have a very unique problem with my Windows 7. Every now and then (that may be between 10 minutes and 4 hours, my system becomes unresponsive for about 60 seconds, while the the hard drive does some mystic thing.
After a lot of logging with PowerShell I came to the conclusion, that there is a definite correspondance between the length of the Current Disk Queue Length and my problem. Especially when Disk Transfers/sec stays at 0.

The current script helps me to determine the exact time when the problem occurs.
But I didn't yet find any corresponding entries in the event-log nor could I determine the process causing this issue.

           

$psold = get-Process

(
'\PhysicalDisk(_total)\Current Disk Queue Length',
'\PhysicalDisk(_total)\Disk Transfers/sec'
) | Get-Counter -cont -sample 1 |% {
$timestamp = "{0:T}" -f $_.Timestamp

$diskQueue = ($_.CounterSamples[0]).CookedValue
$transfer = ($_.CounterSamples[1]).CookedValue

$msg = "{0} {1,4:f0} {2,4:f0}" -f $timestamp, $diskQueue, $transfer

$psnew = get-Process

# Show Processes that started or stopped
Compare-Object $psold $psnew |%{
$ipo = $_.inputObject
$Name = $ipo.ProcessName
$Id = $ipo.Id
if ($_.Sideindicator -eq '=>')
{
"$timestamp Start $Id $Name"
}
if ($_.Sideindicator -eq '<=')
{
"$timestamp Stop $Id $Name"
}
}
$psold = $psnew

# the following code is special to a problem on my Windows 7 installation
# my problem is, when Current Disk Queue Length > 0, but Disk Transfers/sec 0
if ($diskQueue -gt 0 -and $transfer -eq 0)
{
$msg
}
}
A typical output on my system looks like this

PS C:\Var\bin> C:\Var\bin\topics\Perfmon\disk2.ps1
11:49:28 Start 7840 MultipleFirefoxLoader
11:49:30 Start 7036 firefox
11:49:30 Stop 7840 MultipleFirefoxLoader
11:50:16 Stop 6176 SearchFilterHost
11:50:16 Stop 3664 SearchProtocolHost
11:50:31 Stop 7036 firefox
11:50:44 Stop 1936 WmiPrvSE
11:51:23 1 0
11:52:44 1 0
11:54:44 1 0
11:54:47 1 0
11:54:48 1 0
11:54:49 1 0
11:54:51 4 0
11:54:52 4 0
11:54:53 9 0
11:54:54 9 0
11:54:55 10 0
11:54:56 10 0
11:54:57 10 0
11:54:59 10 0
11:55:00 11 0
11:55:01 11 0
11:55:02 11 0
11:55:03 11 0
11:55:04 11 0
11:55:05 11 0
11:55:06 11 0
11:55:08 11 0
11:55:09 11 0
11:55:10 11 0
11:55:11 12 0
11:55:12 15 0
11:55:13 Start 3252 audiodg
11:55:13 16 0
11:55:14 17 0
11:55:16 17 0
11:55:17 17 0
11:55:18 17 0
11:55:19 18 0
11:55:20 Start 5028 svchost
11:55:20 19 0
11:55:21 19 0
11:55:23 19 0
11:55:24 20 0
11:55:25 20 0
11:55:26 20 0
11:55:27 20 0
11:55:28 20 0
11:55:29 20 0
11:55:31 20 0
11:55:32 20 0
11:55:33 21 0
11:55:34 21 0
11:55:35 21 0
11:55:36 21 0
11:55:37 22 0
11:55:38 22 0
11:55:40 22 0
11:55:41 22 0
11:56:12 Stop 7712 chrome
11:56:28 Start 7712 chrome


In Resource Monitor that looks like this:

Samstag, 5. Dezember 2009

Using PowerShell to filter the eventlog

Since I'm using Windows 7 in a domain where we use Microsoft Forefront Client Security I have a little problem. About every 60 minutes my computer becomes unresponsive for about 60 seconds, the hard disk led is on.

In the Application Eventlog I find pairs of Events 21268, 21269. Googling around I seem to be the only one with this special problem.

Some hints say my domain admin has to change some settings, so that my local computer can increase a local buffer. Chances to convince the forefront guys that they do some real nonsence here ( why not just ask me, whether I allow to increase the buffer) or to convince my admin to get some advice from his forefront consultant seem very low.

What the hell fills the buffer. Looking at the Security log, I see that there are lots of audit Failures.

OK, I'm not interessted in audit fails, I don't want to log them. No chance some domain policy doesn't allow me to switch off auditing of rejected packages.

Oh funny thing: I'm allowed to disable the firewall. I'm not going to try this option.

It's time to look deeper into Microsoft Eventlogs.

Seems they are very legacy application, like ipconfig and inifiles. Main information is returned as name:value pairs in plan text.

The Windows Filtering Platform has blocked a connection.

Application Information:
Process ID: 1020
Application Name: \device\harddiskvolume2\windows\system32\svchost.exe

Network Information:
Direction: Inbound
Source Address: 192.168.1.33
Source Port: 60100
Destination Address: 168.143.162.100
Destination Port: 443
Protocol: 0

Filter Information:
Filter Run-Time ID: 212121
Layer Name: Receive/Accept
Layer Run-Time ID: 44


It's time to use a little PowerShell, to convert eventlog data to properties of PowerShell objects, which can be grouped etc.

function Convert-PairToProperty2            
{
process
{
$hash = @{}

$_ -split "`r?`n" | % {
if (.{$m = [regex]::Matches($_,'(\w.*?):\s*(.*)');$m[0]})
{
# Write-Host $m[0].groups[1].value
# Write-Host $m[0].groups[2].value
$hash[ ($m[0].groups[1].value)] = ($m[0].groups[2].value)
}
}
New-Object PSObject -Property $hash
}
}

if ($False)
{
'abc:123
efg:456'
|Convert-PairToProperty2
}

if (! $seclog_1000)
{
Write-host "Collecting last 1000 packets rejected"
(Measure-Command{$seclog_1000 = get-Eventlog security -InstanceId 5152 -newest 1000 | select message }).Milliseconds
}
else
{
'Using $seclog_1000'
}
$time_property2 = Measure-Command { $property2 = ($seclog_1000 | Convert-PairToProperty2) }

"needed $($time_property2.Milliseconds) for property2"

$property2 |group-object -property 'Source Address' -noelement |Sort-object count -desc



If you are taking a closer look, you see that I used http://blogs.msdn.com/powershell/archive/2009/12/05/new-object-psobject-property-hashtable.aspx to convert a hash to properties.

I tried different variants, but performance measurements don't show clear preferences for one or the other.

What I got is clear information which ip address causes most rejected packages.