Get Common Data

While judging entries in this year’s Scripting Games I realized there were some common properties that were repeatedly used. This got me thinking about a simple way to retrieve that information with a single command Then you could access the data values from within your script. I’ve put together a relatively simply function called Get-Common that you might find helpful.

There’s nothing fancy about this function.

I gathers a number of what I think of as common values such as username, computername, PowerShell host and whether the user is running as an administrator. The function writes a custom object to the pipeline, using New-Object.

Assuming you have dot sourced the function, you could use it in your script like this:

Maybe this will help simplify your scripts or maybe it won’t. Of course you can easily extend it to include other core or common data you use frequently in your scripts. If there’s something you add, I’m curious to learn what it is.

Download Get-Common.

Get File Hash

The other day I had the need to calculate MD5 file hashes in order to compare files. The PowerShell Community Extensions has a nifty cmdlet, Get-Hash, that does exactly that. Unfortunately, sometimes even free tools like this aren’t an option, as in the case of my client. Or they don’t go far enough. So with a little work I wrote my own function to compute a file hash using either MD5, SHA1, or SHA256. Continue reading

Friday Fun: Let’s Play Bingo!

Today Campers we’re playing Bingo. Or at least getting ready to. This week I have some PowerShell code that will create a BINGO card. For those of you outside of North America you might need to take a crash course on this game. But even if you don’t play, this article will demonstrate some useful PowerShell concepts and cmdlets like arrays. Get-Random and New-Object. Continue reading

Objects are the answer

As I usually do, I was helping out in the forums at ScriptingAnswers.com. A member had several variables that he wanted to show as a group. As is almost always the case, the answer in PowerShell is object. I talk about this all the time in classes, conferences and online chitchat. Let me offer up a script that demonstrates how objects are the answer.

My business need was to report on files found in a given folder or path. I wanted to get a breakdown of file types showing me the number of each type, their total size and their percentage of all files by count and size.

The script takes a path as a parameter but defaults to your documents folder. Get-Childitem retrieves all files. I’m setting the –errorAction parameter to silentlycontinue to avoid the annoying error messages you get when trying to read protected system folders. The collection of files are then grouped by extension. Each group is then analyzed.

At this point I have a number of pieces of information to display. In a VBScript I would have most like written some message to the screen for each file type. Technically I could do the same thing here but why? Using New-Object I create a new object with properties for all my data. The objects written to the pipeline can be manipulated just like any other object. Let me check my C: drive.

PS C:\> $c=c:\scripts\filestats.ps1 “c:\”

Hmmm…how many different file types are on my computer?

PS C:\> $c.count
1897

Which file types are taking the most space?

PS C:\> $c | sort totalsizeMB -desc | select -first 10 -property * -ExcludeProperty Files | format-table -auto

TotalSizeMB PercentTotal Total Extension PercentSize

———– ———— —– ——— ———–

115692.94 0.0637 %        90 .vmdk     57.8050 %

19559.24 0.0219 %        31 .iso      9.7726 %
14375.12 0.0014 %         2 .vdi      7.1824 %

12440.64 14.8798 %    21018 .dll      6.2159 %
6972.15 2.4778 %      3500 .exe      3.4836 %
6190.48 0.0064 %         9 .wim      3.0930 %

2884.98 0.1373 %       194 .CAB      1.4415 %

2672.56 0.0021 %         3 .m4v      1.3353 %

1424.91 0.0042 %         6 .sav      0.7119 %
1202.12 0.0092 %        13 .mp4      0.6006 %

My custom object even includes a property, files, which itself is a collection of objects. For example, what are the .vdi files?

PS C:\> $c | where {$_.extension -eq “.vdi”} | select -ExpandProperty Files

Directory: C:\VirtualBox\Exchange

Mode                LastWriteTime     Length Name
—-                    ————-     —— —-
-a—         6/29/2010   1:58 PM 1507336243 ExchangeHDD.vdi

Directory: C:\VirtualBox\R2

Mode                LastWriteTime     Length Name
—-                    ————-     —— —-
-a—         6/21/2010   9:34 PM      41472 ExchangeStore.vdi

The bottom line is that having objects offers tremendous possibilities. So the next time you’re working on a PowerShell problem, know that objects are the answer.

My script was intended as a demonstration but if you’d like a copy

Get Parent Process

parent-child Recently I helping out on a post in the forums at ScriptingAnswers.com. The question centered around identifying processes on a computer and their parent process. There are many ways you could slice and dice this problem using WMI and Get-WmiObject. Getting the parent process ID is pretty simple, but going backwards from there to identify the parent process takes a little PowerShell jujitsu.

Because I love objects (geeky, I know), one angle I pursued created a custom object for each parent process. The object included a few key (at least to me) properties as well as a property that held an array of all child processes.

Here’s an example.

ParentID          : 916
Children          : {@{ProcessID=4068; ProcessName=Moe.exe; Description=Moe.exe
; Created=5/19/2010 8:52:59 AM}, @{ProcessID=4716; ProcessN
ame=SkypeNames2.exe; Description=SkypeNames2.exe; Created=5
/20/2010 8:13:47 AM}, @{ProcessID=1600; ProcessName=VBoxSVC
.exe; Description=VBoxSVC.exe; Created=5/20/2010 11:59:31 A
M}, @{ProcessID=6828; ProcessName=WmiPrvSE.exe; Description
=WmiPrvSE.exe; Created=5/21/2010 7:57:22 AM}}
NumberofChildren  : 4
ParentCreated     : 5/19/2010 8:51:46 AM
ParentProcess     : svchost.exe
Computername      : SERENITY

To get here, I called a function I wrote called Get-ParentProcess.

}#Process
End {

$finish=Get-Date

This is an advanced function so it requires PowerShell 2.0. The actual function includes comment based help. I’ve omitted here.

The function takes a computername as a parameter, defaulting to the local computer. You can pipe names to the function as well. Here’s what happens when you connect to the remote computer using Get-WmiObject.  The collection of Win32_Process objects is sorted by the ParentProcessID and then piped to Group-Object. This created a GroupInfo object. The name property is the parent process ID and the corresponding group are all the child processes.

Each group is then parsed and processed pulling out process information and defining new properties. To get the parent process name I search the saved WMI results looking for a process id that matches the parent process ID I’m checking. If you look back at the Get-WmiObject expression you’ll see I’m taking advantage of the –OutVariable common parameter. The cmdlet’s result is not only passed down the pipeline but also stored in the variable. In this case, $data. When you use –OutVariable just specify the variable name you want to use. You don’t need the $.

For the child processes that are in the group I select a few key properties. $Children will be a collection of custom process objects. This value is used as a property value, among others, in New-Object.

When you run the function, you most likely will notice some parent processes with no name. More than likely this is because the parent process is no longer running.

PS C:\> $r=get-parentprocess

PS C:\Scripts> $r | where {-not $_.parentProcess} | select-object -ExpandProperty Children | Sort Created | format-table –autosize

ProcessID ProcessName               Created
——— ———–               ——-
596 csrss.exe                 5/19/2010 8:51:43 AM

676 wininit.exe               5/19/2010 8:51:44 AM

696 csrss.exe                 5/19/2010 8:51:44 AM

852 winlogon.exe              5/19/2010 8:51:45 AM

3396 explorer.exe              5/19/2010 8:52:39 AM

3988 ToshibaServiceStation.exe 5/19/2010 8:53:07 AM

3564 TWebCamera.exe            5/19/2010 8:53:12 AM

3792 TUSBSleepChargeSrv.exe    5/19/2010 8:53:12 AM

2208 VCDDaemon.exe             5/19/2010 8:53:12 AM

4112 jusched.exe               5/19/2010 8:53:13 AM

4164 vmware-tray.exe           5/19/2010 8:53:14 AM

3656 SWin.exe                  5/19/2010 9:03:57 AM

Even if you don’t have a use for the function, I hope you find some useful scripting techniques.

Update: I’ve been using the PowerShell ISE to create the script files on an x64 platform. The Unicode default can be problematic.  Here is an ANSI version of the file.  I’ll try to remember to stick to ANSI from now on.