Wednesday, March 25, 2009

Get-OpenFile

One of the many nice things about PowerShell it that you can use the existing utilities you’ve got and you love. And then you can enrich them using PowerShell. You do this best by converting the output to objects – which you then can use down the pipeline.

One such example is here. Handle.exe (sysinternals.com) returns open files (and other handles). If you wrap that with a script, you can convert the output to objects and then manipulation is so easy.

Here is Get-Openfile.ps1

param($fileFilter=$(throw "Filter must be specified"))

handle $fileFilter | foreach{
if ($_ -match '^(?<program>\S*)\s*pid: (?<pid>\d*)\s*(?<handle>[\da-z]*):\s*(?<file>(\\\\)|([a-z]:).*)') {
$matches | select @{n="Path";e={$_.file}},@{n="Handle";e={$_.handle}},@{n="Pid";e={$_.pid}},@{n="Program";e={$_.program}}
}
}





Handle must be found via $env:path or an alias. Note the use of –match and $matches and how a regex is used to match the output and easily pick up the relevant parts of the output using names. One advice: Learn regex!



An example




PS C:\Windows\PolicyDefinitions> get-openfile  er.exe

Path Handle Pid Program
---- ------ --- -------
C:\Windows\System32\en-US\... 38 7004 SearchIndexer.exe
C:\Windows\en-US\explorer.... 38 5764 explorer.exe
C:\Windows\SysWOW64\en-US\... 50 8484 explorer.exe



 



I originally called the Path property for File, but to bind the value automatically (in the pipeline), I renamed it to path.



This is nice -




PS> get-openfile  er.exe | dir

Directory: C:\Windows\System32\en-US

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 27-05-2008 09:17 7680 SearchIndexer.exe.mui

Directory: C:\Windows\en-US

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 02-11-2006 16:12 27136 explorer.exe.mui

Directory: C:\Windows\SysWOW64\en-US

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 02-11-2006 16:12 36864 explorer.exe.mui



 


 



And this is just as nice -




PS> get-openfile  er.exe | gps

Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
1554 33 178276 107420 622 863,72 7004 SearchIndexer
957 87 74504 82528 356 465,01 5764 explorer
513 32 28768 34044 203 28,27 8484 explorer



 



I use the method in Get-OpenFile a lot as that provides many advantages.



 







PS. You must be administrator to run handle. Get-OpenFile simply does not return any objects if you are not an admin. Handle.exe does not set $? or $lastexitcode, so checking for the condition is not easy.



PS2. Handle.exe can also display the user name and close handles (Remove-Openfile?). It is left to the reader to implement that. Handle.exe does not display files opened across the network. –a can do that, but the path is a strange \Device\Mup path, so it is excluded.

No comments: