Did you know that you can pipe the output of Get-Process into dir? Don’t believe it? Let me prove it:
PS> Get-Process wi*
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
95 4 1080 2892 32 0.30 536 wininit
126 3 1848 4612 41 1.11 640 winlogon
676 22 28656 20332 187 40.09 2344 WinMail
PS> Get-Process wi* |dir
Directory: Microsoft.PowerShell.Core\FileSystem::E:\Windows\system32
Mode LastWriteTime Length Name
—- ————- —— —-
-a— 8/30/2006 2:21 AM 95232 wininit.exe
-a— 8/30/2006 2:21 AM 306688 winlogon.exe
Directory: Microsoft.PowerShell.Core\FileSystem::E:\Program Files\Windows Mail
Mode LastWriteTime Length Name
—- ————- —— —-
-a— 8/29/2006 5:04 PM 120320 WinMail.exe
So you might ask the question: how is the possible?
The answer is easy: code! 🙂
DIR will operate on anything that has a property called path. You can validate this with a CSV file:
PS> cat data.csv
Path
c:\autoexec.bat
c:\win*
PS> Import-Csv data.csv |Dir
Directory: Microsoft.PowerShell.Core\FileSystem::C:\
Mode LastWriteTime Length Name
—- ————- —— —-
-a— 8/10/2004 11:04 AM 0 autoexec.bat
d—- 9/8/2006 7:13 PM WINDOWS
d—- 5/11/2006 8:50 AM winhec
d—- 10/26/2005 8:48 PM WINNT
d—- 5/9/2006 2:25 PM winrm
So all we had to do was to ensure that Process Objects had a PATH property which mapped to the filename of the executable.
Alas, our friends in the .NET team failed us here – they provided no such Path. But instead of whining, we just rolled up our sleeves and fixed the problem. You see this is one of the key scenarios for the Extended Type System. The people who produce types are just one source of data about the object. To paraphrase Brandon Sullivan – the community is not a potted plant – it has a role to play here. You can extend any type with the data you need. We’ve done that for you for a few objects to show you the way. Let’s look at the PATH property of the Process object:
PS> Get-Process |Get-Member path
TypeName: System.Diagnostics.Process
Name MemberType Definition
—- ———- ———-
Path ScriptProperty System.Object Path {get=$this.Mainmodule.FileName;}
This is a SCRIPTPROPERTY which means “run these scripts to get/set a value” (here we only provide a GETTER). The variable $THIS is set to the Process object that this property is attached to.
Thus when a Process object is piped to DIR, the parameter binder sees that DIR can pipeline objects that have a PATH property so it tries to retrieve this from the Process object which runs the script and returns the value. Its a beatiful thing.
Now you may see some interesting results if the process object does not report a PATH (which is the case for SYSTEM and IDLE). This binds a NULL to DIR which causes a dir of your current directory. As such, you might want to always add a where clause
Get-Process |Where {$_.Path} | Dir
So the question is – why would you ever want to do this? Imagine the case that your system started to act flaky, you might want to know which of the processes was most recently updated. You can do that this way (Note that this uses MSINCE – a utility that I blogged about earlier today):
PS> Get-Process |Where {$_.Path} |Dir |Sort LastWriteTime |
>> Format-Table fullname,
>> @{Label=”Updated (Weeks)”;Expr={MSince$_.LastWriteTime Weeks}} -auto
FullName Updated (Weeks)
——– —————
E:\Windows\system32\CCM\CcmExec.exe 32
E:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 4
E:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 4
E:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 4
E:\Program Files\Microsoft Office\OFFICE12\OUTLOOK.EXE 3
E:\Program Files\Windows Defender\MSASCui.exe 3
E:\Program Files\Windows Mail\WinMail.exe 3
E:\Windows\system32\SearchIndexer.exe 3
E:\Windows\System32\mobsync.exe 3
E:\Program Files\Windows Sidebar\sidebar.exe 3
E:\Windows\System32\snmp.exe 3
E:\Program Files\Windows Media Player\wmplayer.exe 3
E:\Windows\system32\psxss.exe 3
E:\Windows\system32\csrss.exe 3
E:\Windows\system32\csrss.exe 3
E:\Windows\system32\DllHost.exe 3
E:\Windows\system32\Dwm.exe 3
E:\Windows\Explorer.EXE 3
E:\Program Files\Internet Explorer\ieuser.exe 3
E:\Program Files\Internet Explorer\iexplore.exe 3
E:\Program Files\Internet Explorer\IEXPLORE.EXE 3
E:\Program Files\Internet Explorer\iexplore.exe 3
E:\Windows\system32\lsass.exe 3
E:\Windows\system32\lsm.exe 3
E:\Windows\system32\notepad.exe 3
E:\Windows\system32\services.exe 3
E:\Windows\system32\SLsvc.exe 3
E:\Windows\system32\smss.exe 3
E:\Windows\System32\spoolsv.exe 3
E:\Windows\system32\svchost.exe 3
E:\Windows\system32\svchost.exe &nbs
p; 3
E:\Windows\system32\svchost.exe 3
E:\Windows\system32\svchost.exe 3
E:\Windows\system32\svchost.exe 3
E:\Windows\system32\svchost.exe 3
E:\Windows\System32\svchost.exe 3
E:\Windows\system32\svchost.exe 3
E:\Windows\System32\svchost.exe 3
E:\Windows\system32\svchost.exe 3
E:\Windows\system32\svchost.exe 3
E:\Windows\system32\svchost.exe 3
E:\Windows\system32\svchost.exe 3
E:\Windows\System32\svchost.exe 3
E:\Windows\System32\svchost.exe 3
E:\Windows\system32\taskeng.exe 3
E:\Windows\system32\taskeng.exe 3
E:\Windows\system32\taskeng.exe 3
E:\Windows\System32\tcpsvcs.exe 3
E:\Windows\system32\wininit.exe 3
E:\Windows\system32\winlogon.exe 3
E:\Windows\system32\wbem\wmiprvse.exe 3
E:\Windows\system32\wuauclt.exe 3
C:\systemInternals\autoruns.exe 0
This was pretty interesting because if you look at the dates, it is clear that there are 4 waves of change here. The latest is the a SystemInternals utility that I installed today. Then there are a bunch of system processes because I just installed Vista RC1 (3 weeks ago). Then there is the version of PowerShell (4 weeks ago). Then there is CcmExec updated 32 weeks ago. That was curious – I couldn’t image what that could be so I did the following to solve the mystery:
PS> Get-Process CCMEXEC |fl Name,Description,FileVersion,Product
Name : CcmExec
Description : CCM Executive
FileVersion : 2.50.4160.2000 built by: SMS
Product : Systems Management Server
Investigate your system – you’ll discover all sorts of cool things.
Enjoy!
Jeffrey Snover [MSFT]
Windows PowerShell/Aspen Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
PSMDTAG:TYPEEXTENSION: ScriptProperty Process Path
0 comments