Monthly Archive

Categories

Monthly Archives: February 2009

Learning PowerShell – 4 friends

When you start learning PowerShell you will find that it has a massive amount of self discovery built into the system. There are four cmdlets you find yourself using all of the time:

  • Get-Help
  • Get-Command
  • Get-Member
  • Get-PSDrive

Oh.  You want to know what they do – try this

001
"get-help", "get-command", "get-member", "get-psdrive" | 
foreach { Get-Help $_ | select Name, Synopsis | Format-List}

OK this is playing to a certain extent but there are some interesting PowerShell points from this.

We start by creating a list of the cmdlets we want to investigate. These are passed onto the pipeline. Foreach will work with each one of them in turn as it comes along the pipeline. The next very important point is that we have a seperate pipeline within the foreach.

On the inner pipeline we start by using get help with the cmdlet name represented by $_  (you will see a lot of this guy – it represents the object on the pipeline).  We then select the name and the synopsis out of help and use format-list to display.

For detailed investigation of the cmdlets use the full and detailed parameters

001
002
Get-Help Get-Command -Detailed
Get-Help Get-Command -Full

Between these four friends you will be able to learn a lot about PowerShell

 

Technorati Tags: Powershell,Learning

UK PowerShell UG meetings

Speakers for the next two meetings have been finalised.

In March we will be bringing you:

Jonathan Medd on the AD cmdlets in Windows Server 2008 R2

Alan Renouf on VMWare’s VI toolkit

plus there will be an introduction to Regular Expressions in PowerShell

 

In May (date tba in week of May 18-21)

Dmitry Sotnokov of PowerGUI fame will be joining us to speak about PowerGUI and other PowerShell related topics

 

Technorati Tags: PowerShell,User Group

Learning PowerShell

One of the subjects that came up at the PowerShell event last week was how do you go about learning PowerShell.

If I was starting from scratch there are a number of things I would do:

  1. Download and install PowerShell  - use a test environment.
  2. Read the documentation that comes with PowerShell
    • The Getting Started and User Guide are a very good place to begin
  3. Download and read Frank Koch’s free PowerShell books from  http://blogs.technet.com/chitpro-de/archive/2008/02/28/free-windows-powershell-workbook-server-administration.aspx
  4. Don’t try and learn everything about PowerShell at once. Think about problems you need to solve. Think about how PowerShell can help.  Try to create a script to solve it. Use the Newsgroups to help. Repeat as necessary
  5. Get involved in the PowerShell community.  Join in on the newsgroups and share your scripts.

Hope this helps.  There are other steps that come after this and I’ll cover them later.  Point 4 is probably the most important. Put PowerShell to work for you as soon as you can – you get more out of it that way and the time you spend learning will rapidly be repaid.

 

Technorati Tags: PowerShell,Learning

Common parameters

I’ve been looking at the get-diskfreespace function over a number of posts. We’ve been looking a mixture of turning it into a production script and adding the advanced functionality from PowerShell v2.  In this post http://richardsiddaway.spaces.live.com/default.aspx?_c01_BlogPart=blogentry&_c=BlogPart&handle=cns!43CFA46A74CF3E96!2005 we added the

[CmdletBinding()] parameter

As soon as we add this parameter we get a whole bunch of functionality for free.  Our original function had a single parameter for the comptuer name – we now have a whole bunch of them

Get-Command get-diskfreespace | select parametersets

{ [[-computer] ] [-Verbose] [-Debug] [-ErrorAction ] [-WarningAction ] [-ErrorVariable ] [-WarningVariable ]

[-OutVariable ] [-OutBuffer ] }

These are the standard common parameters that we expect to see with any cmdlet.

Next we’ll  look at how we use some of them

 

More colour syntax highlights

In this post - http://richardsiddaway.spaces.live.com/default.aspx?_c01_BlogPart=blogentry&_c=BlogPart&handle=cns!43CFA46A74CF3E96!2025 – I mentioned I had been experimenting with the copy script functionality so that I would get colour copy\paste from PowerShell ISE.  There was a problem in that I couldn’t paste into Live Writer – it crashed.

Lee Holmes has re-written the script -http://www.leeholmes.com/blog/MorePowerShellSyntaxHighlighting.aspx

One slight issue is that you need to create a profile for ISE – called Microsoft.PowershellISE_profile.ps1.  It goes in the WindowsPowerShell folder in the Documents folder of your profile.

In that profile you need the line 

001
002
## add the copy-script function
$psise.CustomMenu.Submenus.Add("Copy Script", {C:\Scripts\ISE\copy-script.ps1}, "Shift+Ctrl+Z")

This will add the script onto the custom menu in ISE. 

When you come to paste into Live Writer – use Edit – Paste Special – Keep Formatting  to get the colour syntax highlights.  Notice in this version that you get line numbers as well.  This will be useful for writing about the scripts

This seems to work OK – I’ll experiment so more and report back.

 

Technorati Tags: PowerShell,ISE,Colour output

Enter the Clones

Following my comments about PowerShell being designed for the Jedi - http://richardsiddaway.spaces.live.com/default.aspx?_c01_BlogPart=blogentry&_c=BlogPart&handle=cns!43CFA46A74CF3E96!2066 – I discovered the Clones are now getting into the action - http://www.leeholmes.com/blog/MakingPerfectChangeWithTheFewestCoins.aspx

Lee (of Cookbook fame) has a very nice script for working out the smallest number of coins needed to make perfect change ie meet the price without needing change back.

The script makes very clever use of the Clone() method of a hash table – a clone can be regarded as a copy of the object in this case – and then builds an array of hash tables to hold the results.  For each possible value of 1 – 99 a hash table is created showing which coins are required to created that number of cents, pence or whatever

I really recommend that you have a look at this technique.

If you want convert the script to use any other currency just change the hash table – for instance for UK currency it becomes

$coins = @{ 0.50 = 0; 0.20 = 0; 0.10 = 0; 0.05 = 0; 0.02 = 0; 0.01 = 0 }

The other clever bit is the way the results are presented to automatically include the correct currency symbol.   In case you are wondering the results for the UK are

£0.50: 1
£0.20: 2
£0.10: 1
£0.05: 1
£0.02: 2
£0.01: 1

We only need 8 coins to make any amount of change below £1

 

Technorati Tags: PowerShell

Cultured Dates

In this post - http://richardsiddaway.spaces.live.com/default.aspx?_c01_BlogPart=blogentry&_c=BlogPart&handle=cns!43CFA46A74CF3E96!2007 – I talked about the way date strings had to be formatted when we were creating datetime objects -

[datetime]”mm/dd/yyyyy”

I have since discovered its a little bit more complicated than that. 

If we start by examining the culture on my machine.

PS> $host | Select *culture | fl

CurrentCulture   : en-GB
CurrentUICulture : en-US

Notice they are not the same – en-US means I have to use American (US) English for UI based activities but the culture of the machine is set to en-GB which is UK English. To recap the previous post if I am using [datetime] to create the object I need to follow the UICulture – that is use a mm//dd/yyyy format as shown

PS> [datetime]"25/12/2009"
Cannot convert value "25/12/2009" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At line:1 char:11
+ [datetime] <<<< "25/12/2009"
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

PS> [datetime]"12/25/2009"

25 December 2009 00:00:00

If I use get-date to create the object – it doesn’t work using the same rules

PS> Get-Date -Date "12/25/2009"
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "12/25/2009" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At line:1 char:15
+ Get-Date -Date <<<<  "12/25/2009"
    + CategoryInfo          : InvalidArgument: (:) [Get-Date], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand

It does work with the CurrentCulture format – ie UK format of dd/mm/yyyyy

PS> Get-Date -Date "25/12/2009"

25 December 2009 00:00:00

PS> Get-Date "25/12/2009"

25 December 2009 00:00:00

PS> Get-Date 25/12/2009

25 December 2009 00:00:00

Just to complete the set you can also create dates like this

PS> New-Object -TypeName System.DateTime -ArgumentList 2009,12,25

25 December 2009 00:00:00

Where we use year, month and day as the 3 arguments – this ignores culture completely.

If you are using PowerShell with a machine set for US English [datetime] and get-date work in an identical manner – otherwise be aware that the machine culture will affect how get-date works in this instance.

 

Technorati Tags: PowerShell,Dates

Machine UpTime

The February copy of TechNet magazine dropped through the letter box this morning. In the UK we get our own version so some of this may be a bit older than this months edition.  There is a nice article by Marco Shaw on using PowerShell with System Center Operations Manager that is well worth reading.

The article that really got me thinking was the one about calculating server uptime using information from the event logs. The script is actually measuring the availability of the event log service but it is very close to the available time.

One thing that really leapt out was that the main script was using PowerShell v2 – it had a #Requires –version 2.0

statement at the top.  As v2 is still in CTP that didn’t seem right.  The whole script looked over complicated so I started playing around and came up with this:

$days = 30
$now = Get-Date
$start = (Get-Date -Hour 00 -Minute 00 -Second 00).AddDays(-$days)
"Checking Last Boot Time"
$os = Get-WmiObject -Class Win32_OperatingSystem
$lastboot = $os.ConvertToDateTime($os.LastBootUpTime)
if ($lastboot -lt $start){ Write-Host "Server continually up for whole period"; Return}
else {Write-Host "Server restarted since start of period - analysis continuing"}

"Reading Event Logs"
$events = Get-EventLog -LogName system | where{(($_.EventId -eq 6005) -or ($_.EventId -eq 6006)) -and $_.TimeGenerated -ge $start } | Select EventId, TimeGenerated, Index

## should start with a 6005 - log service started event
if ($events[0].EventId -eq 6005){
    $totaluptime = $now - $events[0].Timegenerated
}
else {
    Write-Host "Error reading log - startup is not first entry"
    Return
}

#check the last
$last = $events | select -Last 1
if ($last.EventId -eq 6006){      ## shutdown
    $totaluptime += ($last.TimeGenerated - $start)
}

## events should be paired 6006\6005 shutdown & start respectively
for ($i = 1; $i -le $events.count-2; $i += 2){
    if ($events[$i].EventId -eq 6006){      ## shutdown
        if ($events[$i+1].EventId -eq 6005){      ## Startup
            $totaluptime += ($events[$i].Timegenerated - $events[$i+1].Timegenerated)
        }
        else {
            Write-Host "Error in log sequence at " $event[$i+1]
            Return    
        }
    }
    else {
        Write-Host "Error in log sequence at " $event[$i]
        Return    
    }
}
## calculate uptime
$totaltime = $now - $start
$percUptime = (($totaltime.TotalHours - $totaluptime.TotalHours)/$totaltime.TotalHours)*100

"Uptime for period $($start.ToLongDateString()) to $($now.ToLongDateString())"
"Total time available: {0:n2} hours" -f $($totaltime.TotalHours)
"Total Uptime: {0:n2} hours" -f $($totaluptime.TotalHours)
"Percentage Uptime: {0:n2} %" -f $percUptime
"Percentage Downtime: {0:n2} %" -f (100 - $percUptime)

 

We start by defining some variables – the number of days we want to analyse, current date and our starting point.

The first check is on when the server was actually started – if it was before the beginning of our period then we have 100% up time and the bonus is in the bank.  We can check this using WMI.  The only awkward bit is converting the boot time to a format we can work with.

Assuming that our server was started since the start of out analysis period then we need to look at the logs.  We can read the system event log looking for eventids 6005 and 6006 as shown. We only want events since the start of our period.

The event logs are writing in chronological order and are returned in the same order with the youngest returned first.  I have yet to see an instance of pulling information from the logs when this wasn’t the case.

The first (youngest) event should be a 6005 – event log service started.  We create a timespan by subtracting that time from the current time which gives us up time since the last restart. If this isn’t the case then we have a problem that needs to be investigated so the script stops.

A check is made to see if the last event is a shutdown – in which case we need to calculate the uptime from the start of the period to shutdown and add it to the total.

The 6005\6006 events should be paired after this with a 6006 (shutdown) followed by a 6005 (startup) – remember we are working backwards in time.  Assuming we find our pairs of events as expected we calculate the timespan between the events and add it to our total uptime.  If the pairings don’t match up then we have an issue to be investigated so the event information is written to screen to give a starting point for analysis.

We then calculate the total timespan of our period and the percentage uptime.  Finally we print out our results.

I think this is easier to follow and seems to work correctly in my testing environment. Remember that this runs on the local machine as written.  It can be made to work on remote machines – Get-WmiObject accepts a computer name parameter as does get-eventlog in PowerShell v2.  If you are using v1 then you could access the remote logs using WMI.

 

Why Powershell is for the Jedi

It just has to be.  Do you know how many cmdlets use the force?  In CTP 3 try

get-help * -Parameter Force

 

Technorati Tags: PowerShell,Jedi

Friday 13th

As today is Friday 13th with all of the implications that holds – who me superstitious? – I thought I would find out other days of the year I needed to hibernate

function fri13 {
param ($year)
    for ($m=1; $m -le 12; $m++) {
        $d = [datetime]"$m/13/$year"
        if ($d.DayOfWeek -eq "Friday"){
            $d.ToLongDateString()
        }
    }
}

The function takes a year as the parameter and iterates through the months building dates for the 13th of each month. Remember that the date is always mm/dd/yyyy format when creating dates like this.  The date is built using string substitution – that is just so useful.

A check on the day of the week for the date and if is a friday the date is listed out.

The function is called as

fri13 2009 

If you want to check for a number of years then we can use a loop

for ($y=2009; $y -le 2014; $y++) {  fri13 $y}

Just in case you were wondering – these are the days to be aware of

13 February 2009
13 March 2009
13 November 2009
13 August 2010
13 May 2011
13 January 2012
13 April 2012
13 July 2012
13 September 2013
13 December 2013
13 June 2014

Lets be careful out there.

 

Technorati Tags: PowerShell,dates