MCPMag.com

Sign up for our newsletter.

I agree to this site's Privacy Policy.

Prof. Powershell

Where Shell We Begin?

Customize graphical elements of the user's desktop via the Shell.Application COM object. Yes, it can be done through PowerShell.

Back in the day, when VBScript was the admin scripting tool of choice, many an administrator took advantage of the Shell.Application COM object. This object offered some handy hooks into the graphical elements of a user's desktop. PowerShell can also take advantage of that object, which means you can add graphical features to your command-line scripts.

To begin with we need to create an instance of the Shell.Application object using the New-Object cmdlet:

$shell=new-object -com "shell.application"

I'll let you pipe this to Get-Member to whet your appetite. Instead, I want to use this object to present a graphical interface so a user can select a folder. From the console the only tool we have to take user input interactively is the Read-Host cmdlet. But then the user would have to type the name correctly and we'd need validation code to verify the folder exists. A graphical folder picker would be nicer so we'll use the shell object's BrowseForFolder() method.

At a minimum you should specify a handle, 0 will suffice, a window title and an options value. Again, 0 will suffice:

$fldr=$shell.BrowseForFolder(0,"Select a Folder",0)

You can also add a parameter to indicate a starting root:

$fldr=$shell.BrowseForFolder(0,"Select a Folder",0,"c:\")

What gets a little tricky is working with the result because it is a COM object:

PS S:\> $fldr

Title                      : backup
Application                : System.__ComObject
Parent                     :
ParentFolder               : System.__ComObject
Self                       : System.__ComObject
OfflineStatus              :
HaveToShowWebViewBarricade : False
ShowWebViewBarricade       : False

What I need is a path that can be used elsewhere. The “trick” is to grab the SELF property:

PS S:\> $fldr.self

Application  : System.__ComObject
Parent       : System.__ComObject
Name         : backup
Path         : C:\backup
GetLink      :
GetFolder    : System.__ComObject
IsLink       : False
IsFolder     : True
IsFileSystem : True
IsBrowsable  : False
ModifyDate   : 12/19/2010 7:03:14 PM
Size         : 0
Type         : File folder

This property is a nested object with its own set of properties. But I can easily get the path now:

PS S:\> $fldr.self.path
C:\backup

Here's a short demonstration script that prompts the user to browse for a folder then writes a custom object to the pipeline with the number of files, the average file size and a few other goodies:

$shell=new-object -com "shell.application"
$fldr=$shell.BrowseForFolder(0,"Select a Folder to Analyze",0,"c:\")
$path=$fldr.self.path
write-host "Examining $path" -ForegroundColor Green
#filter out folders so that only files are measured
$stats=dir -Path $path -Recurse | where {-not $_.PSIsContainer} |
   Measure-Object -Property Length -sum -max -average
#write a custom object
New-Object -TypeName PSObject -Property @{
   Path=$path
   FileCount=$stats.count
   AverageSize=$stats.average
   TotalSize=$stats.Sum
  LargestFile=$stats.maximum
}

As great as you think this might be, there is one cosmetic drawback when run on x64 platforms: The BrowseForFolder() method writes event information to the console when you browse for a folder. When you run the script in the PowerShell console you'll see messages like these:

start request
signaling finishcondition
start request
signaling finishcondition
start request
signaling finishcondition

You don't see the messages when running the script in the ISE or other editor like PowerGUI or SAPIEN's PrimalScript. I also found there are no messages when run in an x86 PowerShell session on a 64-bit operating system. The script and shell object work in all cases. It's just a matter of the ugly event messages.

About the Author

Jeffery Hicks is a Microsoft MVP in Windows PowerShell, Microsoft Certified Trainer and an IT veteran with over 20 years of experience, much of it spent as an IT consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He works today as an independent author, trainer and consultant. Jeff writes the popular Prof. PowerShell column for MPCMag.com and is a regular contributor to the Petri IT Knowledgebase and 4SysOps. If he isn't writing, then he's most likely recording training videos for companies like TrainSignal or hanging out in the forums at PowerShell.org. Jeff's latest books are Learn PowerShell 3 in a Month of Lunches, Learn PowerShell Toolmaking in a Month of Lunches and PowerShell in Depth: An Administrators Guide. You can keep up with Jeff at his blog http://jdhitsolutions.com/blog, on Twitter at twitter.com/jeffhicks and on Google Plus (http:/gplus.to/JeffHicks)

comments powered by Disqus

Reader Comments:

Add Your Comment Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above