Powershell

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)!

Powershell

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: }

[ download ] | [ view or revise my code on poshcode.org ]

Powershell

(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.

Powershell

powerscripting logo

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.  :)

2008-7
15

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…

Powershell

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

image

Technorati Tags:

Powershell

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!

Powershell

This is a screencast to show you how to use the excellent program launcher
Launchy, to quickly execute PowerShell commands.

Music

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!

image

Powershell

image

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!