In another case of the web team not talking to the marketing team, looks like the VI Toolkit for Windows is available for download—before the formal release!
Rather than give you the gory details here (125 cmdlets—woo hoo!), I’ll refer you to a gentleman who has been working with VMware for much longer than I have: Eric Sloof. Watch his blog, I expect he’ll be highlighting this shortly.
And of course, when my book, Managing VMware Infrastructure with PowerShell: TFM is ready, that will be a very fine source of information on the subject. :) I still don’t have a date yet but definitely “this year”.
Oh and last but not least, we have Carter Shanklin in studio (ok—on the phone) for Eposide 34 of the PowerScripting Podcast. That show will air Friday or Saturday (Aug 1st), so watch for that.
Happy PowerShelling (with VMware)!
These functions will allow you to easily save a set of credentials to disk so that they can be reused during an unattended session later. There are a few blog entries and newsgroup posts about this topic elsewhere, and Lee Holmes covers it in his “PowerShell Cookbook”, but nothing that I have seen actually helps you do the end-to-end of credential –> disk –> credential process. Hope you find it useful! I wrote this for my book, but as it’s of general use I thought I would share.
Update: 7/21/08 @ 11:16a
I’m changing the import conditions to work better on v1 of PowerShell. Download link has updated code.
Update: 7/21/08 @ 7:10p
Reader Steve S. pointed out to me that if you give Export-PSCredential a username, it does not work, but he expected it to. I agreed, so changed the logic a bit. I like it this way, now it works just like Get-Credential does (try get-credential “username” to see what I mean).
One last thing—big props to Brandon Shell who has written on this topic as well. In fact, I umm, er, was troubleshooting that script with him when he wrote it so I should know better. To be fair, I—ok I have no excuse. But I didn’t mean to steal any well-deserved thunder. ;) My script does store the username where his does not, although he says he’s got an updated one which does. Even so—the more the merrier so that you can see multiple ways to solve a problem.
1: # Author: Hal Rottenberg <hal@halr9000.com>
2: # Url: http://halr9000.com/article/tag/lib-authentication.ps1
3: # Purpose: These functions allow one to easily save network credentials to disk in a relatively
4: # secure manner. The resulting on-disk credential file can only [1] be decrypted
5: # by the same user account which performed the encryption. For more details, see
6: # the help files for ConvertFrom-SecureString and ConvertTo-SecureString as well as
7: # MSDN pages about Windows Data Protection API.
8: # [1]: So far as I know today. Next week I'm sure a script kiddie will break it.
9: #
10: # Usage: Export-PSCredential [-Credential <PSCredential object>] [-Path <file to export>]
11: # Export-PSCredential [-Credential <username>] [-Path <file to export>]
12: # If Credential is not specififed, user is prompted by Get-Credential cmdlet.
13: # If a username is specified, then Get-Credential will prompt for password.
14: # If the Path is not specififed, it will default to "./credentials.enc.xml".
15: # Output: FileInfo object referring to saved credentials
16: #
17: # Import-PSCredential [-Path <file to import>]
18: #
19: # If not specififed, Path is "./credentials.enc.xml".
20: # Output: PSCredential object
21:
22: function Export-PSCredential {
23: param ( $Credential = (Get-Credential), $Path = "credentials.enc.xml" )
24:
25: # Look at the object type of the $Credential parameter to determine how to handle it
26: switch ( $Credential.GetType().Name ) {
27: # It is a credential, so continue
28: PSCredential { continue }
29: # It is a string, so use that as the username and prompt for the password
30: String { $Credential = Get-Credential -credential $Credential }
31: # In all other caess, throw an error and exit
32: default { Throw "You must specify a credential object to export to disk." }
33: }
34:
35: # Create temporary object to be serialized to disk
36: $export = "" | Select-Object Username, EncryptedPassword
37:
38: # Give object a type name which can be identified later
39: $export.PSObject.TypeNames.Insert(0,’ExportedPSCredential’)
40:
41: $export.Username = $Credential.Username
42:
43: # Encrypt SecureString password using Data Protection API
44: # Only the current user account can decrypt this cipher
45: $export.EncryptedPassword = $Credential.Password | ConvertFrom-SecureString
46:
47: # Export using the Export-Clixml cmdlet
48: $export | Export-Clixml $Path
49: Write-Host -foregroundcolor Green "Credentials saved to: " -noNewLine
50:
51: # Return FileInfo object referring to saved credentials
52: Get-Item $Path
53: }
54:
55: function Import-PSCredential {
56: param ( $Path = "credentials.enc.xml" )
57:
58: # Import credential file
59: $import = Import-Clixml $Path
60:
61: # Test for valid import
62: if ( !$import.UserName -or !$import.EncryptedPassword ) {
63: Throw "Input is not a valid ExportedPSCredential object, exiting."
64: }
65: $Username = $import.Username
66:
67: # Decrypt the password and store as a SecureString object for safekeeping
68: $SecurePass = $import.EncryptedPassword | ConvertTo-SecureString
69:
70: # Build the new credential object
71: $Credential = New-Object System.Management.Automation.PSCredential $Username, $SecurePass
72: Write-Output $Credential
73: }
(This post is the second in my Solving Problems with PowerShell series.)
Problem: Extract list of IP addresses and ping them
So I had a bunch of text in a webpage form which looked like this:
[172.16.16.139] (2.0.39) [172.16.16.31] (2.0.40) [172.16.16.189] (2.0.40) [172.16.16.156] (2.0.45) [172.16.15.89] (2.0.46) [172.16.16.81] (2.0.46) [172.16.16.73] (2.0.47) [172.16.16.31] (2.0.48) [172.16.15.106] (2.0.49) [172.16.16.238] (2.0.49) [172.16.15.14] (2.0.54) [172.16.15.79] (2.0.54)
My goal was to ping each host to see if they were alive. Here’s how I went about that process.
Step One – Get the data into PowerShell
After copying the above into the clipboard, I used PowerShell’s “here-string” feature to quickly get the list into a variable. I just typed this into a console window:
$a = @"
Then I hit enter, then ctrl-V, followed by another enter (so that its on a line by itself) and this:
"@
Now, $a contains the string I want to match against.
Step Two – Parse the text
This one was easier than you may think because I had done some prep some months ago for just such an occasion. There’s this really cool tool Expresso (website appears down, uh oh! google similar results to the rescue!) which helps you to graphically create a regular expression which can then be used to for parsing text. That tool came with a library of commonly used regular expressions, one of which was made to match IP addresses. To save time for when I might need to use it, I have this in my profile which loads when PowerShell is started:
New-Variable -Name RegexIP -Force `
-Description "A regular expression object which matches and validates IP addresses." `
-Value ([regex]'(?<First>2[0-4]\d|25[0-5]|[01]?\d\d?)\.(?<Second>2[0-4]\d|25[0-5]|[01]?\d\d?)\.(?<Third>2[0-4]\d|25[0-5]|[01]?\d\d?)\.(?<Fourth>2[0-4]\d|25[0-5]|[01]?\d\d?)')
With that in hand, here’s how I parsed the text which was now in the $a variable:
97# $regexip.Matches($a) | select value
Value
-----
172.16.16.139
172.16.16.170
172.16.16.31
172.16.16.189
172.16.16.57
172.16.16.156
172.16.15.89
172.16.16.81
172.16.16.73
172.16.16.31
172.16.16.80
172.16.15.106
172.16.16.238
172.16.15.14
172.16.15.79
Step Three – Ping the male progeny of female dogs!
And lastly, pipe the mess to the Ping-Computer cmdlet which is available from SAPIEN’s PowerShell Extensions (PshX-SAPIEN).
PS > $regexip.Matches($a) | select -ExpandProperty value | Ping-Computer ComputerName StatusCode ResponseTime ProtocolAddress ------------ ---------- ------------ --------------- 172.16.16.139 0 0 172.16.16.139 172.16.16.170 0 0 172.16.16.170 172.16.16.31 0 0 172.16.16.31 172.16.16.189 0 0 172.16.16.189 172.16.16.57 0 1 172.16.16.57 172.16.16.156 0 0 172.16.16.156 172.16.15.89 0 0 172.16.15.89 172.16.16.81 0 0 172.16.16.81 172.16.16.73 0 0 172.16.16.73 172.16.16.31 0 0 172.16.16.31 172.16.16.80 0 0 172.16.16.80 172.16.15.106 0 0 172.16.15.106 172.16.16.238 0 0 172.16.16.238 172.16.15.14 0 0 172.16.15.14 172.16.15.79 0 0 172.16.15.79
Instead of using Select-Object –ExpandProperty, I could have used the Foreach-Object cmdlet in a loop like this:
PS > $regexip.Matches($a) | % { Ping-Computer $_.Value }
Same end result, but I have been using select –exp a lot lately and have gotten used to that technique. To each his own.
So that’s it! I hope this walkthrough helps you out with a problem that you need to solve.
In this episode, Jonathan and I have a panel discussion with Dmitry and Kirk from Quest Software. This was the first try at a Skype call to the other side of the globe. It worked fairly well but the lag was somewhat noticeable. This was also our first panel discussion as opposed to interviews. I think it came out pretty good but I definitely have to hone my moderator skills.
Just playing around. I know I have a few broken bits that I’m still working on. For one thing, that image at the top and the sidebar font have to go…
This screenshot will have to do until I have time to blog and podcast it properly. You can grab the free IIS filter on PowerShellToys.com
This was something implied by Peter Schulz (but not admitted—oh no, he’s in Marketing!) when Jonathan and I interviewed him on the podcast, and I’ve verified it this morning. (See the podcast show notes for links to download WFS.) Have a look-see:
45# Get-PSSnapin -Registered | ? { $_.Vendor -match 'Citrix' } Name : ArdencePSSnapIn PSVersion : 2.0 Description : This is a PSSnapin for Citrix's Provisioning Server commands. Name : NetScalerPSSnapIn PSVersion : 2.0 Description : This is a PSSnapin for Citrix's NetScaler commands. Name : XenAppPSSnapIn PSVersion : 2.0 Description : This is a PSSnapin for Citrix's XenApp commands.
It’s as easy as cake to add these to your session and start messing around. I’ll leave that to someone like Brandon Shell who actually has some of these products laying around.
52# Get-Command -PSSnapin Ard*,NetSc*,Xen* | group pssnapin Count Name Group ----- ---- ----- 26 XenAppPSSnapIn {Add-Application, Add-Server, Connect-Farm, Disable-Appli... 34 ArdencePSSnapIn {Add-Ardence.Client, Add-Ardence.Server, Add-Ardence.vDis... 49 NetScalerPSSnapIn {Add-NetScaler.HTTPService, Add-NetScaler.IP, Add-NetScal... 53# Get-Command -PSSnapin Ard*,NetSc*,Xen* | group verb Count Name Group ----- ---- ----- 10 Add {Add-Application, Add-Ardence.Client, Add-Ardence.Server,... 2 Bind {Bind-NetScaler.LBMonitorToService, Bind-NetScaler.LBVSer... 1 Boot {Boot-Ardence.Client} 4 Check {Check-Ardence.ClientExists, Check-Ardence.ServerExists, ... 3 Clear {Clear-NetScaler.LBMonitorScript, Clear-NetScaler.LBMonit... 1 Close {Close-NetScaler.Connection} 1 Connect {Connect-Farm} 8 Disable {Disable-Application, Disable-NetScaler.IP, Disable-NetSc... 1 Disconnect {Disconnect-Session} 8 Enable {Enable-Application, Enable-NetScaler.IP, Enable-NetScale... 30 Get {Get-Application, Get-Ardence.Client, Get-Ardence.ClientC... 1 Initialize {Initialize-NetScaler.Connection} 1 Logoff {Logoff-Session} 1 Map {Map-Ardence.vDisk} 3 Modify {Modify-ApplicationGroup, Modify-ApplicationUser, Modify-... 1 New {New-Ardence.vDisk} 1 Publish {Publish-Application} 1 Reboot {Reboot-Ardence.Client} 10 Remove {Remove-Application, Remove-Ardence.Client, Remove-Ardenc... 2 Restart {Restart-Ardence.ServerService, Restart-NetScaler.NS} 1 Save {Save-NetScaler.Config} 1 Send {Send-Ardence.ClientMessage} 10 Set {Set-ApplicationAccount, Set-Ardence.Client, Set-Ardence.... 1 Shutdown {Shutdown-Ardence.Client} 1 Start {Start-Ardence.ServerService} 1 Stop {Stop-Ardence.ServerService} 2 Unbind {Unbind-NetScaler.LBMonitorFromService, Unbind-NetScaler.... 1 Unlock {Unlock-Ardence.vDisk} 1 Unmap {Unmap-Ardence.vDisk}
Looks pretty tasty!
This is a screencast to show you how to use the excellent program launcher
Launchy, to quickly execute PowerShell commands.
Whoah. Thanks to @timalexander for passing this one to me. Look at how long that scrollbar is! Click here or on the picture to grab ‘em!
PoshCode is a highly modified pastebin web app (this version written in PHP) which some of us in the community have been using for some time to store our reusable script components.
This tool, formerly hosted on powershellcentral, now has its own domain. Joel “Jaykul†Bennett has been doing a lot of work on it lately, which you can read about here.
New features include:
- RSS feed for new entries
- Improved navigation by author
- Cleaner front page
Once I get around to it, this site will be linked to properly from PowerShellCommunity.
Go forth and share (and steal!) scripts!


