Category Archives: External Feeds

New Technical Product Manager at Provance Technologies


Today is my first day working in my new role as Technical Product Manager at Provance Technologies.  A little while back Provance approached me to talk about this position, and it seemed like a very natural fit.  Rarely have I felt such a positive vibe from a company through the interview process, so I was really happy to accept the position of Technical Product Manager with them and I have been looking forward to starting work with them.

Now that I am working full-time with Provance, I’ll be getting up to speed as quickly as I can on the IT Asset Management Pack and the Data Management Pack products that we offer to help companies properly manage the assets they have inside their organization.  I know there is already some PowerShell support in one of the products, although I haven’t personally taken a look at it yet (but you can bet I will be soon).

For those of you who regularly follow my blog, if you happen to use either of these products in your organization, I’d love to hear about it.

Kirk out.

CIM vs WMI cmdlets-remote execution speed


Following on from my previous post we’ll look at how the two types of cmdlets compare for accessing remote machines.

I used a similar format to the previous tests but was accessing a remote machine.

First off was the WMI cmdlet – using DCOM to access the remote Windows 2012 server

PS> 1..100 |
foreach {
Measure-Command -Expression{1..100 | foreach {Get-WmiObject -Class Win32_ComputerSystem -ComputerName W12SUS }}
} |
Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 2084.122547
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

 

The CIM cmdlets are similar but apparently a bit slower – probably due to having to build the WSMAN connection and teat it down each time.

PS> 1..100 |
foreach {
Measure-Command -Expression{1..100 | foreach {Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName W12SUS }}
} |
Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 2627.287458
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

 

So what happens is you run the CIM command over a CIM session?

PS> $sess = New-CimSession -ComputerName W12SUS
PS> 1..100 |
foreach {
Measure-Command -Expression{1..100 | foreach {Get-CimInstance -ClassName Win32_ComputerSystem -CimSession $sess }}
} |
Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 877.746649999999
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

This removes the setup and tear-down of the WSMAN connection. It suggests that the actual retrieval time for the CIM cmdlets should be reduced to 1749.540808 milliseconds for 100 accesses which is faster than the WMI cmdlets

It looks like the fastest way to access WMI information is across a CIM session. Next time we’ll look at running multiple commands

PowerShell PopUp


popupAt the recent PowerShell Summit I presented a session on adding graphical elements to your script without the need for WinForms or WPF. One of the items I demonstrated is a graphical popup that can either require the user to click a button or automatically dismiss after a set time period. If this sounds familiar, yes, it is our old friend VBScript and the Popup method of the Wscript.Shell object. Because PowerShell can create and use COM objects, why not take advantage of this?

All it really takes is two lines. One line to create the Wscript.Shell COM object and one to invoke the Popup method.  (Yes, I’m sure you could do this in one line, but that’s not the point.)

$wshell = New-Object -ComObject Wscript.Shell -ErrorAction Stop
$wshell.Popup("Are you looking at me?",0,"Hey!",48+4)

The Popup method needs parameters for the message, title, a timeout value, and an integer value that represents a combination of buttons and icons.

popup2The challenging part has always been trying to remember the integer values. So I wrote a quick function called New-Popup.

#requires -version 2.0

Function New-Popup {

<#
.Synopsis
Display a Popup Message
.Description
This command uses the Wscript.Shell PopUp method to display a graphical message
box. You can customize its appearance of icons and buttons. By default the user
must click a button to dismiss but you can set a timeout value in seconds to 
automatically dismiss the popup. 

The command will write the return value of the clicked button to the pipeline:
  OK     = 1
  Cancel = 2
  Abort  = 3
  Retry  = 4
  Ignore = 5
  Yes    = 6
  No     = 7

If no button is clicked, the return value is -1.
.Example
PS C:\> new-popup -message "The update script has completed" -title "Finished" -time 5

This will display a popup message using the default OK button and default 
Information icon. The popup will automatically dismiss after 5 seconds.
.Notes
Last Updated: April 8, 2013
Version     : 1.0

.Inputs
None
.Outputs
integer

Null   = -1
OK     = 1
Cancel = 2
Abort  = 3
Retry  = 4
Ignore = 5
Yes    = 6
No     = 7
#>

Param (
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter a message for the popup")]
[ValidateNotNullorEmpty()]
[string]$Message,
[Parameter(Position=1,Mandatory=$True,HelpMessage="Enter a title for the popup")]
[ValidateNotNullorEmpty()]
[string]$Title,
[Parameter(Position=2,HelpMessage="How many seconds to display? Use 0 require a button click.")]
[ValidateScript({$_ -ge 0})]
[int]$Time=0,
[Parameter(Position=3,HelpMessage="Enter a button group")]
[ValidateNotNullorEmpty()]
[ValidateSet("OK","OKCancel","AbortRetryIgnore","YesNo","YesNoCancel","RetryCancel")]
[string]$Buttons="OK",
[Parameter(Position=4,HelpMessage="Enter an icon set")]
[ValidateNotNullorEmpty()]
[ValidateSet("Stop","Question","Exclamation","Information" )]
[string]$Icon="Information"
)

#convert buttons to their integer equivalents
Switch ($Buttons) {
    "OK"               {$ButtonValue = 0}
    "OKCancel"         {$ButtonValue = 1}
    "AbortRetryIgnore" {$ButtonValue = 2}
    "YesNo"            {$ButtonValue = 4}
    "YesNoCancel"      {$ButtonValue = 3}
    "RetryCancel"      {$ButtonValue = 5}
}

#set an integer value for Icon type
Switch ($Icon) {
    "Stop"        {$iconValue = 16}
    "Question"    {$iconValue = 32}
    "Exclamation" {$iconValue = 48}
    "Information" {$iconValue = 64}
}

#create the COM Object
Try {
    $wshell = New-Object -ComObject Wscript.Shell -ErrorAction Stop
    #Button and icon type values are added together to create an integer value
    $wshell.Popup($Message,$Time,$Title,$ButtonValue+$iconValue)
}
Catch {
    #You should never really run into an exception in normal usage
    Write-Warning "Failed to create Wscript.Shell COM object"
    Write-Warning $_.exception.message
}

} #end function

The function lets you use text descriptions for the buttons and icons. In PowerShell 3.0 you will also get tab completion for the possible values. This makes it easy to create a command like this:

new-popup "Do you want to get work done with PowerShell?" -Title "Hey, you!" -Buttons YesNo -Icon Question

The function writes the value of the clicked button to the pipeline. I expect this is something you are more apt to use in a script. Perhaps to display an error message or even to prompt the user for an action. Maybe you’d like to use it in your PowerShell 3.0 profile:

$r = New-Popup -Title "Help Update" -Message "Do you want to update help now?" -Buttons YesNo -Time 5 -Icon Question
if ($r -eq 6) {
  Update-Help -SourcePath \\jdh-nvnas\files\PowerShell_Help -Force
}

The popup will automatically dismiss after 5 seconds unless I click Yes or No. You should be able to copy the function text from the listing above by toggling to plain code, select all and copy.

I hope you’ll let me know where you use this.

CIM cmdlets vs WMI cmdlets–speed of execution


One question that came up at the summit was the comparative speed of execution of the new CIM cmdlets vs the old WMI cmdlets.  No of us knew the answer because we’d never tried measuring the speed.

I decided to perform some tests.

This first test is accessing the local machine.  In both cases the cmdlets are using COM.  WMI uses COM and CIM will use COM if a –ComputerName parameter isn’t used.

The results are as follows:

PS> 1..100 |
foreach {Measure-Command -Expression {
1..100 | foreach {Get-WmiObject -Class Win32_ComputerSystem} }
} | Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 2008.953978
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

 

PS> 1..100 |
foreach {Measure-Command -Expression {
1..100 | foreach {Get-CimInstance -ClassName Win32_ComputerSystem} }
} | Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 2078.763174
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

 

So for pure COM access the WMI cmdlets are marginally (3.4%) faster.

What if we use the ComputerName parameter?

PS> 1..100 |
foreach {
Measure-Command -Expression {
1..100 | foreach {Get-WmiObject -Class Win32_ComputerSystem -ComputerName $env:COMPUTERNAME } }
} | Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 1499.14379
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

PS> 1..100 |
foreach {
Measure-Command -Expression {
1..100 | foreach {Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $env:COMPUTERNAME } }
} | Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 3892.921851
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

This one surprised me – the WMI cmdlets are 2.5 times faster.  I suspect that is because the CIM cmdlet has to build and then breakdown the WSMAN connection each time.

Next time we’ll look at accessing a remote machine.

Time for D-CRUD?


I was thinking on the plane back from the PowerShell summit about the CRUD activities. They are a concept we have inherited from the database world:

C = Create

R = Read

U = Update

D= Delete

Create, Update and Delete correspond directly to the PowerShell verbs – New,Set and Remove respectively.

The Read action corresponds to the Get verb.

Well sort of.

Get-* is used in two distinct scenarios.  Firstly we know of an object and we we want to read its properties – for example:

Get-Process -Name powershell

We are reading the information about the PowerShell process. That corresponds directly to the Read action in the CRUD paradigm.

However, we also use Get* when we want to Discover the processes that are running:

Get-Process

In which case we are Discovering the processes that are running.

I think its time to update the CRUD concept and make it DCRUD where D stands for discovery.

Scripting Games 2013 have started


The 2013 Scripting Games kicked off during the PowerShell summit.  Event 1 is open and you can submit entries up until 23:59:59 GMT on 29 April 2013.  Voting on the entries starts at at midnight on 30 April.

You can enter and you can vote on the entries.  This is a community games run by powershell.org – all are welcome.

If you haven’t entered yet there is still plenty of time to get you entry in for event 1.  Start by reviewing the information at http://powershell.org/wp/the-scripting-games/

Enjoy and good luck

PowerShell Summit–thank you


I’d like to extend a huge thank you to everyone who attended the PowerShell Summit this last week.  The Summit was a success – in no small part due to you. Your questions, and discussions, are what this is all about.

It was a pleasure meeting you all and I hope to return next year – I hope to see many of you there as well.

PowerShell Summit 2013 Kicks Off


I’m very excited to be in Redmond for a few days as part of the PowerShell Summit. I love catching up with old friends and making new ones all over PowerShell. If you couldn’t make it this year, and I know many of you will feel you are missing out, there’s always next year. We are making plans to accommodate more people in 2014.

I’ll also be trying to tweet and blog what I can over the next few days.

Friday Fun PowerShell Commands by Noun


One of PowerShell’s greatest strength’s is discoverability. Once you know how, it is very easy to discover what  you can do with PowerShell and how. One reason this works is because PowerShell commands follow a consistent verb-noun naming convention. With this in mind, you can see all of the commands organized by noun.

get-command -CommandType cmdlet | sort noun,verb | format-table -group noun

This will work in both v2 and v3.

get-command-noun-01In PowerShell 3.0, this will display commands from all modules, even those not currently loaded. If you want to limit your display to only those modules currently imported use this:

get-command -CommandType cmdlet -ListImported | sort noun,verb | Format-Table -group noun

Or you can use this same idea to organize cmdlets in a specific module.

get-command -mod hyper-v | sort Noun,Verb | format-table -group Noun

get-command-noun-02Now that you know what you can do, go forth and do it!

PowerShell Deep Dives–another MEAP release


 

Manning have released another set of chapters in their early access program for PowerShell Deep Dives.

If you have an interest in PowerShell I would strongly urge you to buy a copy. It has chapters from a number of well known PowerShell authors together with some very good material from new authors.  Best of all the royalties are going to charity.

PowerShell Deep Dives–another MEAP release


 

Manning have released another set of chapters in their early access program for PowerShell Deep Dives.

If you have an interest in PowerShell I would strongly urge you to buy a copy. It has chapters from a number of well known PowerShell authors together with some very good material from new authors.  Best of all the royalties are going to charity.

Busy, busy, busy


A very busy time coming up in PowerShell land with the first PowerShell Summit kicking off in just over a week’s time.  The 2013 Scripting Games will also be starting very soon.

I’ll try and post about both of them as time allows

Creating a new disk


I really like Windows Server Core. The concept has come of age in Windows 2012.

I needed to add a new disk to a virtual machine  – that’s easy using the Hyper-V cmdlets. But what about formating the disk.

A module new to Windows 2012 & Windows can be used.  Its the Storage module.  I’ve not had chance, or reason, to play with this module yet. So many cmdlets so little time.

Start with viewing the disks:

PS C:\Users\richard> Get-Disk | ft -a

Number Friendly Name          OperationalStatus Total Size Partition Style
—— ————-          —————– ———- —————
0      Virtual HD ATA Device  Online                120 GB MBR
1      Microsoft Virtual Disk Offline               127 GB RAW

 

Disk 1 is the new disk so need to initialise it.

PS C:\Users\richard> Initialize-Disk -Number 1 -PartitionStyle MBR

View the disks again

PS C:\Users\richard> Get-Disk | ft -a

Number Friendly Name          OperationalStatus Total Size Partition Style
—— ————-          —————– ———- —————
0      Virtual HD ATA Device  Online                120 GB MBR
1      Microsoft Virtual Disk Online                127 GB MBR

 

Create a partition on the disk –   -useMaximimSize means use all of the disk for this partition

PS C:\Users\richard> New-Partition -DiskNumber 1 -UseMaximumSize -DriveLetter R

Now view the partitions

PS C:\Users\richard> Get-Partition | ft -a

   Disk Number: 0

PartitionNumber DriveLetter Offset         Size Type
————— ———– ——         —- —-
1                           1048576      350 MB IFS
2               C           368050176 119.66 GB IFS

   Disk Number: 1

PartitionNumber DriveLetter Offset    Size Type
————— ———– ——    —- —-
1               R           1048576 127 GB Logical

And finally format the new disk:

PS C:\Users\richard> Get-Volume | where DriveLetter -eq R | Format-Volume -FileSystem NTFS -NewFileSystemLabel Backup

Confirm
Are you sure you want to perform this action?
Warning, all data on the volume will be lost!
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  Suspend  [?] Help (default is “Y”): Y

You get a nice friendly warning (you could bypass using –Confirm $false) and the format happens

You could pipe the cmdlets together to do everything in one pass. Best of all – the cmdlets are WMI based.

Friday Fun: Get-Anniversary


Recently I celebrated a wedding anniversary. Even though I didn’t forget I could have used a little help. So I figured since I’m in PowerShell all the time anyway, it could help. I built a little script to remind me of important dates. Let me walk you through the key steps.

First, I’ll define a variable for the anniversary date.

[datetime]$anndate="5/6/2007"

I picked a date coming up. Next, it isn’t too difficult to calculate the number of days between two dates. But what I needed to do is find May 6th for this year. Here’s how I did it:

[datetime]$thisYear = "$($anndate.month)/$($anndate.day)"

$thisYear is now May 6, 2013. Excellent, because now I can get the number of days until that date.

$when = $thisYear - (Get-Date)

$when is a TimeSpan object.

Days              : 23
Hours             : 11
Minutes           : 25
Seconds           : 42
Milliseconds      : 300
Ticks             : 20283423003384
TotalDays         : 23.4761840316944
TotalHours        : 563.428416760667
TotalMinutes      : 33805.70500564
TotalSeconds      : 2028342.3003384
TotalMilliseconds : 2028342300.3384

I can use the Days property in my message. Although the other item of information I wanted is the number of years for the anniversary. Very important. Again, because we’re working with objects all I need to do is subtract the Year properties between the anniversary date and today.

$NumYears = (Get-Date).year - $anndate.Year

At this point I could simply display a message that tells me how many days are remaining until anniversary #X. But let’s go a step further. How about displaying the number of years as an ordinal? For example, 5th or 23rd anniversary. To do that I did a quick search to see if someone had already figured this out, since there is no .NET specific method to accomplish this. I found some code samples and converted them into a PowerShell function.

Function Get-Ordinal {

Param([int]$i)

Switch ($i %100) {
 #handle special cases
 11 {$sfx = "th" } 
 12 {$sfx = "th" } 
 13 {$sfx = "th" } 
 default {
    Switch ($i % 10) {
        1  { $sfx = "st" }
        2  { $sfx = "nd" }
        3  { $sfx = "rd" }
        default { $sfx = "th" }
    } #inner switch
 } #default
} #outerswitch
 #write the result to the pipeline
 "$i$sfx"
} #end Get-Ordinal

Basically you take the number and perform a modulo operation. Based on the result I know what suffix to use and the function writes the ordinal string to the pipeline, like 1st or 7th.  With that, all that is left to do is display my message.

$msg = "Your {0} anniversary is in {1} days." -f (Get-Ordinal $NumYears),$when.Days

Let me show you the complete script.

Param (
#what is the anniversary date
[datetime]$anndate="5/6/2007"
)

#a function to create ordinal numbers
Function Get-Ordinal {

Param([int]$i)

Switch ($i %100) {
 #handle special cases
 11 { $sfx = "th" } 
 12 { $sfx = "th" } 
 13 { $sfx = "th" } 
 default {
    Switch ($i % 10) {
        1  { $sfx = "st" }
        2  { $sfx = "nd" }
        3  { $sfx = "rd" }
        default { $sfx = "th"}
    } #inner switch
 } #default
} #outerswitch
 #write the result to the pipeline
 "$i$sfx"
} #end Get-Ordinal

#how many years
$NumYears = (Get-Date).year - $anndate.Year

#create the anniversary date for this year
[datetime]$thisYear = "$($anndate.month)/$($anndate.day)"

#is anniversary next year?
if ($thisYear -lt (Get-Date)) {
  #add a year"
  $thisYear=$thisYear.AddYears(1)
  $NumYears++
}

#how soon is the anniversary?
$when = $thisYear - (Get-Date)

#define an empty hashtable for parameters
$phash = @{}

if ($when.Days -gt 0) {
  $msg = "Your {0} anniversary is in {1} days." -f (Get-Ordinal $NumYears),$when.Days
  $phash.Add("Object",$msg)
  $phash.Add("Foregroundcolor","Green")
}
else {
  $msg = "Your {0} anniversary is in {1} hours and {2} minutes!" -f (Get-Ordinal $NumYears),$when.hours,$when.minutes
  $phash.Add("object",$msg)
  $phash.Add("Foregroundcolor","Red")
  #Find a florist!!
  start "http://www.google.com/#hl=en&output=search&q=florist"
}

Write-Host @phash

The only other special feature of this script is that if the number of days is greater than one, the message is display using Write-Host in green.

get-anniversary

BUT, if you are down to 1 day or less you get the message in red AND your browser will open up to a Google search for Florists. I’m trying to help you out as much as I can. You could call this script from your PowerShell profile and (hopefully) never forget another anniversary or important date. Or you might simply take away some tidbits about datetime objects, timespans and splatting. Either way I think you come out ahead.

Enjoy.

UPDATE April 16, 2013
I realized my original code had a problem: if the anniversary date was next year you would get a negative result. For example if the anniversary was yesterday, the script would say your anniversary was in -1 days. That won’t work. So I added some code to test the anniversary date compared to the current date. If it is less than today, meaning it has already passed, then I need to add a year.

if ($thisYear -lt (Get-Date)) {
  #add a year"
  $thisYear=$thisYear.AddYears(1)
  $NumYears++
}

Now when I calculate the difference between $thisYear and today, I’ll get a positive number. I suppose I should rename the variables because $thisYear, in this case, is actually the date for the anniversary next year. I’m also incrementing the value of the number of years is updated.

The other thing to take away from this, and something that I neglected to do (shame on me) is to test based on data that will fail as well as succeed. For this script, I neglected to test for dates that have already passed.