January 2011 - Posts

COM pt 5–FileSystem Object

I haven’t finished with the WScript.Shell object and we will return to it.  This time I want to look at the FileSystem object. If you have worked with VBScript and files you will be familiar with this object.  While we have techniques in PowerShell to perform many of the same tasks there are still a few places where using this object can save effort.

For instance getting the size of  folder.  We can use get-childitem and use measure-object on the output but that gets a bit messy. An alternative is to do this

001
002
003
004
005
006

$fso = New-Object -ComObject "Scripting.FileSystemObject"
$top = $fso.GetFolder("c:\test")
"{0,-20} {1,12}" -f $top.Path, $top.Size
foreach ($sf in $top.SubFolders) {
"{0,-20} {1,12}" -f $sf.Path, $sf.Size
}

 

Create the FileSystem object and get the folder we are interested in.  Display the Path and Size properties.

we can then use the SubFolders collection to loop through the and get the path and size of each sub folder.

This is only the first level sub folders – if we want more we need to think about recursion

Posted by RichardSiddaway | with no comments
Filed under: ,

COM pt 4

If you have been following along so far you may be thinking that you can use

ls env:

to view the environmental variables.

True.

But if you compare the output of part 3, the PowerShell enc: drive and getting the environmental variables via WMI you will find that they aren’t identical.

The point of this post is to show that we can combine what we are learning about the WScript objects with “pure” PowerShell.

Look at the path variable – on my test machine I get

PS> $env:path
%SystemRoot%\system32\WindowsPowerShell\v1.0\;C:\Program Files\Common Files\Microsoft Shared\Windows Live;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\jZip;C:\Program Files\TortoiseHg\;C:\Program Files\Windows Live\Shared

 

OK. Now notice the first entry %systemroot%. We can’t resolve that directly in PowerShell but what we can do is this

001
002
003
004
005
006
007
008
009
010
011
012
013
014

function resolve-envar {
param([string]$var
)
 
$wshell = New-Object -ComObject "WScript.Shell"
 $wshell.ExpandEnvironmentStrings("$var"
)
}


$data = $env:path -split "\\"
0..$($data.length -1) | foreach
 {
 
if ($data[$($_)] -match "%.*%"
) {
 
$data[$($_)] = resolve-envar $data[$($_)]
 }
}

$path = $data -join "\"
$path

 

We get the path and split it at the \ folder delimiters.  We need to use \\ as \ is interpreted as an escape character. We examine each element in the path -  a range operator is less typing than a for loop – and if it is of the form %…….% we use the resolve-envar function to expand it.

We can then stick the bits back together again and display the path.

Not something we are likely to use every day but it does show how we can drop bits of functionality into our scripts when they are the easiest way to do things.

Posted by RichardSiddaway | with no comments
Filed under: ,

COM pt 3–More shell

Last time we looked at the Environment parameterized property

If you ran the script in part two the output would have contained things like

windir=%SystemRoot%

We need to be able to resolve the variable %SystemRoot% part to the full path

001
002
003
004
005
006
007
008
009
010
011
012
013
014

$wshell = New-Object -ComObject "WScript.Shell"
"System"
, "User", "Process", "Volatile" |
foreach {
"`n$($_)"
 $envars  = $wshell.Environment($($_))
 foreach ($envar in $envars){
   if ($envar -match "%.*%"){
   $s = ($envar -split "%")[1]
   $exp = $wshell.ExpandEnvironmentStrings("%$s%")
   $envar.Replace("%$s%", $exp)
  }
  else {$envar }
 }
}

 

We can take the script from part 2 and modify it slightly. Once we have the environmental variables for each area we loop through them and find those that contain the pattern “%.%”. This is a simple regular expression (I only do simple regex.  Maybe I’ll get more adventurous after the March UG group when we have a guest speaker on regex) that looks for two % signs separated by some characters.

If we find that we split on the % and take the second element – push it through the ExpandEnvironemtStrings method and plus the result back into the environmental variable.

Posted by RichardSiddaway | with no comments
Filed under: ,

Reminder 1

Quick reminder that the UK PowerShell UG meeting for February is coming up soon.

Details from here http://msmvps.com/blogs/richardsiddaway/archive/2011/01/18/uk-user-group-february-live-meeting.aspx

 

That reminds me – I’d better write the presentation  Smile

Science or Art

Infrastructure Architecture = Science or Art. Discuss.

We claim the titles of architect and/or engineer but is what we do as infrastructure architects really based on solid scientific/engineering principles.

I would claim not. Much of what we do is recycling the designs of the past – possibly adapting them as new versions of particular technologies appear. But how many times have you seen an implementation of version 3 of product that is implemented in exactly the same way as version 1 would have been. The reason is usually the very lame “but we’ve always done it that way”. The real reason in many cases is that the people involved haven’t bothered to keep up to date with changes in the technologies they are relying on. This means their organisations aren’t getting the full benefit of those applications.

There are a number of fundamental architectural decisions that in many cases are driven by the existing environment. How many truly green field sites are there these days?

There are a larger number of design decisions which are often based on the products we select.

In this way we are more like the master masons that built the great cathedrals of the Middle Ages. We know what works and we stick with it.

So. Science or Art?

Posted by RichardSiddaway | with no comments
Filed under:

COM pt3–WScript.Shell

One thing that we seem to forget when we use PowerShell is the functionality that was available to us in VBScript through the Windows Scripting Host (WSH) objects. Much of this functionality has been duplicated in PowerShell cmdlets or through .NET classes but there is still a good pile of stuff we can use.  I think its time to stir up that pile and have a look at what we can find. The great thing about this functionality is:

  • its available on all Windows boxes
  • there are many VBScript examples we can reuse

The WScript object is the top of the tree as far as WSH is concerned bit it doesn’t really do much for us. Lets drop down a level and look at the WScript.Shell object.

 

PS> $wshell = New-Object -ComObject "WScript.Shell"
PS> $wshell

 

Name                     MemberType
----                     ----------
AppActivate              Method
CreateShortcut           Method
Exec                     Method
ExpandEnvironmentStrings Method
LogEvent                 Method
Popup                    Method
RegDelete                Method
RegRead                  Method
RegWrite                 Method
Run                      Method
SendKeys                 Method
Environment              ParameterizedProperty
CurrentDirectory         Property
SpecialFolders           Property

 

The properties look interesting lets start there.  Special folders are the desktop etc which we will look at later. Current directory is obvious.

The Environment property is listed as a parameterized property – this means we have to give it a value

001
002
003
004
005
006

$wshell = New-Object -ComObject "WScript.Shell"
"System"
, "User", "Process", "Volatile" |
foreach {
"`n$($_)"
$wshell.Environment($($_))
}

 

We have four possibilities which gives us a nice break down of the environmental variables.  It supplies a bit more info than

dir env:

The Environment property may look like a method but it isn’t really.

We do have a set of methods to play with

AppActivate
CreateShortcut
Exec
ExpandEnvironmentStrings
LogEvent
Popup
RegDelete
RegRead
RegWrite
Run
SendKeys

which we will start looking at later.

Posted by RichardSiddaway | with no comments
Filed under: , ,

Watching the file arrival

I picked up a question in the ITKE forums about a script to watch the file system

 

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016

function eventhandler {
param ($e)
 Write-Host "File: $($e.SourceEventArgs.FullPath) has arrived"
}


$folder = "C:\test"
$filter = "*"
$fsw = New-Object -TypeName System.IO.FileSystemWatcher `
-ArgumentList $folder, 
$filter
$fsw
.IncludeSubDirectories = 
$true

$action
 = {eventhandler $($event)}

Register-ObjectEvent -InputObject $fsw -EventName "Created" `
 -SourceIdentifier "File System Creation" -Action $action

 

The event handler function accepts the event as a parameter and writes out that a file has been received. You can put anything in here eg a mail message could be sent.

The folder and filter (all files) are set and we define the FileSystemWatcher object which we set to include subdirectories

The action is defined and the event is registered.

dot source the script when you run it

Posted by RichardSiddaway | with no comments

COM pt 2–More Shell

$shell = New-Object -ComObject "Shell.Application"

gets us a shell object.  We can then see the methods available to us

 

PS> $shell | gm -MemberType method | Format-Wide -Column 2


AddToRecent           BrowseForFolder
CanStartStopService   CascadeWindows
ControlPanelItem      EjectPC
Explore               ExplorerPolicy
FileRun               FindComputer
FindFiles             FindPrinter
GetSetting            GetSystemInformation
Help                  IsRestricted
IsServiceRunning      MinimizeAll
NameSpace             Open
RefreshMenu           ServiceStart
ServiceStop           SetTime
ShellExecute          ShowBrowserBar
ShutdownWindows       Suspend
TileHorizontally      TileVertically
ToggleDesktop         TrayProperties
UndoMinimizeALL       Windows
WindowsSecurity       WindowSwitcher

 

$shell.MinimizeAll()
$shell.UndoMinimizeAll()

Are fairly obvious in what they do.

$shell.Toggledesktop()

will also minimise all open windows. but it isn’t reversed by UndoMinimizeAll().

$shell.Windows()

may cause some confusion as it represents a collection of all of the open windows that belong to the Shell. It does not show open all open Windows.

$shell.Windows() | select name, type, statustext

return these windows

Windows Internet Explorer
Windows Internet Explorer
Windows Internet Explorer
Windows Internet Explorer
Windows Explorer

Which is right for the shell.  I have IE open with 4 active tabs and Windows Explorer. What this doesn’t show is that I also have PowerShell, MSDN library, LiveWriter and LiveMail open. 

The lesson is to be careful and read the documentation.

$shell.Explore("folder-name")

could be useful for instance

$shell.Explore("c:\scripts")

will open Windows Explorer pointing at the scripts folder.

Posted by RichardSiddaway | with no comments
Filed under: ,

COM pt 1

In April I will be doing a User Group Live Meeting on using COM with PowerShell.  It is such a wide topic I thought I’d start a few posts to set some background – it also helps my reasearch

COM is the way applications were built for the Windows platform before .NET appeared.  Ugh pre-historic stuff that no one cares about I hear you shout.

Opps. Not really

COM is still around a happily surviving today. For instance the Office applications, IE and the Windows Scripting Host functionality are all COM based

We can discover some information about the COM based applications installed in our systems by using

Get-WmiObject -Class Win32_COMApplication | sort Name | Select Name

This will generate a very long list – don’t be surprised if the early entries have a blank name. Unfortunately the name doesn’t always reflect what we need to use to work with the COM object.

For instance the list of applications generates these examples

Shell ChkdskEx Dialog
Shell Computer Accounts
Shell Computer Groups
Shell Execute Hardware Event Handler
Shell FMIFS Wrapper
Shell Hardware Mixed Content Handler
Shell Hardware Mixed Content Handler Cancelled
Shell Security Editor
ShellWindows

 

if we search for ShellWindows for instance  -  http://msdn.microsoft.com/en-us/library/bb773974(VS.85).aspx  - we see that it represents a collection of open windows belonging to the shell. In many cases COM objects are based on a hierarchy and we have to start at the top of hierarchy.

If you work around in the documentation you will often find a topic that describes the scripting interface or scripting objects. Scripting is somewhere in the title e.g. http://msdn.microsoft.com/en-us/library/bb773177(v=VS.85).aspx

 

If we hunt around in the list we find the shell object which “Represents the objects in the Shell. Methods are provided to control the Shell and to execute commands within the Shell. There are also methods to obtain other Shell-related objects.”

 

This sounds promising so we follow it to http://msdn.microsoft.com/en-us/library/bb774094(v=VS.85).aspx where we find in the properties section a reference to the objects’s Application object.  Bingo – just what we want.

Unfortunately we don’t get much in the way of examples so we have to go back to what we can work out. If you have seen any COM based PowerShell you know that we use the New-Object cmdlet and if you look in the help you find this

$shell = New-Object -ComObject "Shell.Application"

This structure is what we will often see – the name of the object followed by .Application.  If we are working with Word it becomes

$word = New-Object -ComObject "Word.Application"

Let’s go back to the Shell and find out what it does

$shell | gm

It has methods and properties just like .NET so what do we have

$shell.TileVertically()

is fun

$shell.TileHorizontally() supplies a bit of amusement but don’t have too many Windows open when you use them otherwise you will spend a while sorting them out

Some of the other methods look useful so we’ll explore them later

Posted by RichardSiddaway | with no comments
Filed under: ,

System Restore Points

I’ve just started a series on using the WMI system restore classes to work with remote machines at http://itknowledgeexchange.techtarget.com/powershell/

The functions developed in this series will become the next PSAM module

Architecture and Design

When we are talking about IT infrastructure the terms architecture and design seem to be used with identical meaning – even by practising architects who should know better.

The two concepts are quite different.

A architecture is how we want deliver – the concept if you like.  I have seen this level labelled as conceptual design which in many ways is a better label than architecture. As an example we will consider the Windows server estate of an organization. It has been decided that architecturally the roadmap is to virtualise. Our architecture looks like this

  • Server farm  - hosts for virtualisation
  • hyper-visor and management system for virtual machines
  • SAN based storage for virtual machines

For simplicity I’ll leave out backup, networks etc etc. They are assumed to be present.

Notice that I haven’t mentioned a single product. Architectures are product agnostic.

A design is what we will actually implement.

There are a number of designs we could create to satisfy this architecture.

For instance:

  • 5 IBM based servers
  • VMware + vcenter
  • IBM SAN

or

  • 5 HP servers
  • Microsoft Hyper-V + SC Virtual Machine Manager
  • EMC SAN

we could continue building options. In many cases buying policy and/or existing infrastructure dictate the solution.

In any case these designs have the same architecture but they have different designs and implementations.

Architecture is product independent – Design is when we decide on the components we are using and pick the products.

Posted by RichardSiddaway | with no comments
Filed under:

First time sighting

I received an unsolicited job spec today – first time I’ve seen one with PowerShell listed as the essential skill

Now is definitely the time to start learning PowerShell if you haven’t already

Posted by RichardSiddaway | with no comments
Filed under:

Location stacks

We saw that push-location stores the current location and changes the location to the specified folder.  The location is stored on a stack. A stack is exactly what it sounds like. Think of a stack of plates. Each plate represents a location. The first location (plate) goes on the bottom and all subsequent locations (plates) pushed on to the stack and piled on top in order so that last stored location is on top.

We can see this by trying a number of push-locations.

Push-Location c:\test
Push-Location hklm:
Push-Location software\microsoft
Push-Location c:\teszzt2
Push-Location c:\scripts

 

We can then see the locations on the stack

PS> Get-Location -Stack

Path
----
C:\teszzt2
HKLM:\software\microsoft
HKLM:\
C:\test
C:\scripts

 

Stacks are unloaded from the top

PS> 1..5 | foreach {pop-location; get-location}

Path
----
C:\teszzt2
HKLM:\software\microsoft
HKLM:\
C:\test
C:\scripts

 

and now the stack is empty.

PS> Get-Location -Stack

 

it is possible to use the StackName parameter with push- & pop- location but that could get complicated and difficult to keep track of

Posted by RichardSiddaway | with no comments

get-scripting PowerShell Podcast

I recently recorded an episode of the get-scripting podcast which is produced by fellow PowerShell MVP Jonathan Medd.  The podcast is available from

http://get-scripting.blogspot.com/2011/01/get-scripting-podcast-episode-21.html

 

During the session we discuss:

 

I enjoyed recording the podcast and hope you will support Jonathan’s efforts by continuing to listen to future episodes

UK User Group–February Live Meeting


When: Tuesday, Feb 8, 2011 7:30 PM (GMT)


Where: Live Meeting

*~*~*~*~*~*~*~*~*~*

An introductory session showing how to get the most out of PowerShell’s utility cmdlets. These are
Compare-Object
ForEach-Object
Group-Object
Measure-Object
New-Object
Select-Object
Sort-Object
Tee-Object
Where-Object
Suitable for beginners and the odd possible surprise for experts

Notes


Richard Siddaway has invited you to attend an online meeting using Live Meeting.
Join the meeting.
Audio Information
Computer Audio
To use computer audio, you need speakers and microphone, or a headset.
First Time Users:
To save time before the meeting, check your system to make sure it is ready to use Microsoft Office Live Meeting.
Troubleshooting
Unable to join the meeting? Follow these steps:

  1. Copy this address and paste it into your web browser:
    https://www.livemeeting.com/cc/usergroups/join
  2. Copy and paste the required information:
    Meeting ID: 5D2B4R
    Entry Code: h_>SF*D9q
    Location: https://www.livemeeting.com/cc/usergroups

If you still cannot enter the meeting, contact support

Notice
Microsoft Office Live Meeting can be used to record meetings. By participating in this meeting, you agree that your communications may be monitored or recorded at any time during the meeting.

Location, location

The location cmdlets don’t seem to get used very much from the scripts I have seen. There are four cmdlets dealing with location:

Get-Location
Pop-Location
Push-Location
Set-Location

In its simplest use Get-Location supplies the path to the current folder

PS> Get-Location

Path
----
C:\scripts

 

Set-Location can be used to change folders.  It is aliased to

cd
chdir
sl

PS> Set-Location -Path dns
PS> Get-Location

Path
----
C:\scripts\dns

 

Push and pop are a bit more interesting

 

Push-location can be used to store the current location and jump to another location

PS> Push-Location -Path hklm:\software
PS> Get-Location

Path
----
HKLM:\software

 

Pop-location can be used to return us to our starting point

PS> Pop-Location
PS> Get-Location

Path
----
C:\scripts\dns

 

thats the basics covered but there is a bit more we do with locations as we will see

Posted by RichardSiddaway | with no comments
Filed under:

UK PowerShell User Group Meetings

Please note the following dates for your diaries:

 

8 February – PowerShell utility cmdlets

An introductory session showing how to get the most out of PowerShell’s utility cmdlets.  These are

Compare-Object
ForEach-Object
Group-Object
Measure-Object
New-Object
Select-Object
Sort-Object
Tee-Object
Where-Object

 

22 March – Regular Expressions

PowerShell MVP Tome Tanasovski will present on Regular Expressions.  This is an opportunity to learn more about an under used part of PowerShell.

Tome is a Windows engineer for a market-leading global financial services firm in New York City. He is a recipient of the PowerShell MVP award, the founder and leader of the New York City PowerShell User group, a blogger, and a regular contributor to Microsoft's Windows PowerShell forum. He has been featured four times on Hey Scripting Guy, and he is currently working on the PowerShell Bible, which is due out in 2011 from Wiley.

http://powertoe.wordpress.com

http://twitter.com/toenuff

 

12 April – PowerShell and COM

PowerShell has great support for WMI and .NET but don’t forget that many applications still only have a COM interface. This session will also cover accessing the Windows Scripting Host functionality. 

All sessions start at 7.30pm UK time unless stated otherwise.  (Note that UK goes to daylight saving time on 20 March)

Posted by RichardSiddaway | with no comments

PowerShell colours

The background and text colours for a PowerShell instance (not ISE) can be set through the properties of the window. There are a set of colours for the background and text of:

  • Error messages
  • Warning Messages
  • Debug info
  • Verbose output
  • Progress bars

that cannot be set in this manner.

There is a PowerShell 2.0 automatic variable called $host that will display information about the current instance of PowerShell.

These two facts are related how?

$host has a property called privatedata. This isn’t some super secret hidey hole to tuck away the bits of information you don’t want anyone else to read. It actually contains the colour settings we discussed above. On a default PowerShell install you will get:

PS> $host.privatedata


ErrorForegroundColor    : Red
ErrorBackgroundColor    : Black
WarningForegroundColor  : Yellow
WarningBackgroundColor  : Black
DebugForegroundColor    : Yellow
DebugBackgroundColor    : Black
VerboseForegroundColor  : Yellow
VerboseBackgroundColor  : Black
ProgressForegroundColor : Yellow
ProgressBackgroundColor : DarkCyan

 

These settings can be changed by simply put a line such as

$host.privatedata.ErrorBackgroundColor = "White"

into your profile.  If you only want a temporary change simply type it at the prompt.   The allowed colours are:

Black            White 
DarkBlue         Blue 
DarkGreen        Green 
DarkCyan         Cyan
DarkRed          Red 
DarkMagenta      Magenta  
DarkYellow       Yellow 
DarkGray         Gray

Posted by RichardSiddaway | with no comments
Filed under:

PowerShell and WMI - Chapter 4

Chapter 4 has been released for PowerShell and WMI. It is available through the Manning Early Access Program (MEAP) at http://www.manning.com/siddaway2/

The first 4 chapters cover:

  1. Solving Administrative Challenges
  2. Using PowerShell
  3. WMI in Depth
  4. Best Practices

Chapters 5 and 6 covering System Configuration Information and Disk Systems respectively are in the pipeline.  I’m currently working on chapter 7 on the registry. Chapters 5 onwards include lots of lovely scripts.

Posted by RichardSiddaway | with no comments

PowerShell Best practices

Ed Wilson – Microsoft Scripting Guy – gave a superb presentation to the UK PowerShell group tonight.  If you missed it the recording will be available for the next 365 days

You have been invited you to view a Microsoft Office Live Meeting recording.
View Recording
Recording Details
    Subject: Windows PowerShell Best Practice
    Recording URL:
https://www.livemeeting.com/cc/usergroups/view
    Recording ID: PPS9QQ
    Attendee Key: M5<|wdK;8

I would recommend this to everyone interested in using PowerShell.  You need to listen to the end if you want to find out Ed’s number one, must do, best practice

Posted by RichardSiddaway | with no comments
Filed under:
More Posts Next page »