Categories

Monthly Archives: January 2009

Live Writer Problem

Just come across an odd problem with Live Writer.  Experimenting with the copy-script function from http://blogs.msdn.com/powershell/archive/2009/01/13/how-to-copy-colorized-script-from-powershell-ise.aspx

I created a simple script and ran the copy script command and tried to paste into Live Writer.  No go.  Live Writer stops working!!

I can paste the script into Word and then do another cut and paste but I get extra formatting spreading the lines too far apart. One method that does seem to work is to paste the code into the editor on my blog, then copy the HTML that is produced into Live Writer. This gives the required result but the server won’t accept the formatting.

Only way to make this work is to post the code directly into an entry that is being created on the blog.  Shame.

XML to Word

Found an interesting challenge on the WinIT magazine forum.  Take an XML file

<recipe name="bread" prep_time="5 mins" cook_time="3 hours">
<title>Basic bread</title>
<ingredient amount="8" unit="dL">Flour</ingredient>
<ingredient amount="10" unit="grams">Yeast</ingredient>
<ingredient amount="4" unit="dL" state="warm">Water</ingredient>
<ingredient amount="1" unit="teaspoon">Salt</ingredient>
<instructions>
<step>Mix all ingredients together.</step>
<step>Knead thoroughly.</step>
<step>Cover with a cloth, and leave for one hour in warm room.</step>
<step>Knead again.</step>
<step>Place in a bread baking tin.</step>
<step>Cover with a cloth, and leave for one hour in warm room.</step>
<step>Bake in the oven at 180(degrees)C for 30 minutes.</step>
</instructions>
</recipe>

and turn it into a Word document.  I came up with this as a first pass.  Length of the script can be cut by using functions

## remove existing document
$file = "c:\scripts\test.doc"
if (Test-Path $file){Remove-Item -Path $file}
## read xml file
[xml]$x = Get-Content -Path c:\scripts\test.xml

## open word document
$word = New-Object -ComObject "Word.application"
$word.visible = $true
$doc = $word.Documents.Add()
$doc.Activate()

## recipe title
$word.Selection.Font.Name = "Cambria"
$word.Selection.Font.Size = "20"
$word.Selection.TypeText($x.recipe.title)
$word.Selection.TypeParagraph()

$word.Selection.Font.Name = "Calibri"
$word.Selection.Font.Size = "11"
$word.Selection.TypeText("Preparation Time = $($x.recipe.prep_time)")
$word.Selection.TypeParagraph()

$word.Selection.Font.Name = "Calibri"
$word.Selection.Font.Size = "11"
$word.Selection.TypeText("Preparation Time = $($x.recipe.cook_time)")
$word.Selection.TypeParagraph()
## ingredients
$word.Selection.Font.Name = "Cambria"
$word.Selection.Font.Size = "14"
$word.Selection.TypeText("Ingredients")
$word.Selection.TypeParagraph()

$word.Selection.Font.Name = "Calibri"
$word.Selection.Font.Size = "11"
for ($i=0; $i -le ($x.recipe.ingredient.length -1); $i++){

$ingdnt = $x.recipe.ingredient[$i].amount + " " + $x.recipe.ingredient[$i].unit + " " + $x.recipe.ingredient[$i]."#text" + " " + $x.recipe.ingredient[$i].state
$word.Selection.TypeText($ingdnt)
$word.Selection.TypeParagraph()
}
## instructions
$instructions = $x.recipe.instructions.step | out-string
$word.Selection.Font.Name = "Cambria"
$word.Selection.Font.Size = "14"
$word.Selection.TypeText("Instructions")
$word.Selection.TypeParagraph()
$word.Selection.Font.Name = "Calibri"
$word.Selection.Font.Size = "11"
$word.Selection.TypeText($instructions)
$word.Selection.TypeParagraph()

$doc.SaveAs([REF]$file)
$Word.Quit()

The interesting part is working with XML.  By reading it into [xml]$x we create an xmldocument object.  We can then step through the attributes and the elements, convert them to strings where necessary and output to the word document.  If you’ve not played with XML before its worth spending a little time experimenting at the various levels in the document – especially putting them through get-member.

Couple of points to note.  The way the ingredient element text and the associated attributes are obtained. The way just the instruction steps are retrieved.

Interesting problem.  For this particular file I found it easier to do this way than using Select-XML from CTP 3.  Select-XML is good for investigating XML but you do have to learn XPath syntax

 

Technorati Tags: ,

Certificate Lifespan

Eileen has posted about a fairly long life span for one of the certificates on her machine - http://blogs.technet.com/eileen_brown/archive/2009/01/29/a-very-trusted-certificate.aspx

If you want to find the certificate that will last the longest on your machine – PowerShell is there for you

Get-ChildItem -Path Cert: -Recurse | Sort Notafter -Descending | Select -First 1 | Format-List

use –recurse to dir through all of the certificates – the certificate store is exposed as a drive by PowerShell.  Sort on the Notafter date & select the first.  Format as a list to see all the properties.

Quicker than opening a GUI.

 

CTP 3 – More functions

I realised after my post on advanced functions that I am getting ahead of myself.  Part of what I wanted to do was take the functional code in the original script and wrap it up to make it moe production orientated.  I suspect like many I tend to write scripts to do a job and they then are forgotten about as I move to the next task.  With some of the changes in PowerShell v2 – especially modules and the changes to functions it is time to think about rectifying this.

One thing with v2 functions is that they have 

Begin{}

Process{}

End{}

script blocks available.  They have the same meaning as in foreach in that begin is processed once at the start, process is used at each call and end is called once when the function has finished. If you are just using it once it probably doesn’t matter but if you are going to use it on the pipeline then it does make processing more efficient.  I haven’t made much use of them before but now is the time to start thinking about how they can be used to improve the logic and readability of the function

This makes our function look like this

#Requires -Version 2.0
function Get-DiskFreeSpace
{
    [CmdletBinding()]
    Param ($computer=".")       #default to local machine
   Begin {
       Clear-Host
       # get current foreground colour
       $origFg = $host.ui.rawui.foregroundColor     # get original foreground colour

        # set title line
       $title = "{0,2}  {1,12}  {2,9}  {3,9}  {4,9}  {5,9} " -f "Drive", "Type", "Size",  "Used",  "Avail", "Use%"
    }

    Process {
        #get the disk information
        $diskinfo = Get-WmiObject Win32_LogicalDisk -computer $computer
        if ($computer -ne ".")
        {
            Write-Host "Disk information for "  $computer  `n
        }
        else
        {
            Write-Host "Disk information for local host"  `n
        }

        $title
        foreach ($disk in $diskinfo)
        {
            $size = $disk.Size / 1GB
            $strSize = $size.ToString("F") + "GB"       # format disk size string   
            $avail = $disk.FreeSpace / 1GB
            $strAvail = $avail.ToString("F") + "GB"    # format space available string   
            $used = $size - $avail
            $strUsed = $used.ToString("F") + "GB"    # format space used string
            if ($size -gt 0.0)
            {
                $useperc = ($used / $size) * 100.0
                $strUseperc = $useperc.ToString("F")    # format space available string
            }
            else
            {
                $strUseperc = "0.00"
            }
            # set foreground colour based on percentage free space       
            switch ($useperc)
            {
                {$_ -ge 90.0} {$host.ui.rawui.foregroundColor = "Red"}
                {$_ -lt 90.0 -and $_ -ge 80.0} {$host.ui.rawui.foregroundColor = "Yellow"}
                {$_ -lt 80.0} {$host.ui.rawui.foregroundColor = "Green"}
                default {$host.ui.rawui.foregroundColor = "White"}
            }

            # format output string       
           "{0,2}  {1,15}  {2,9}  {3,9}  {4,9}  {5,9} " -f $disk.Name, $disk.FileSystem,    $strSize, $strUsed, $strAvail, $strUseperc
       }

    }
    End {
       $host.ui.rawui.foregroundColor = $origFg   # reset foreground colour
    }
}
set-alias df get-diskfreespace

I have changed the begin, process and end key words to bold so they are obvious.  Next time we will look at getting this working on the pipeline

 

PowerShell Homework: The answer

In this post - http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!2006.entry – I mentioned the puzzle set by Jeffrey Hicks in his PowerShell column.

If you want the answer it is available at - http://mcpmag.com/columns/article.asp?editorialsid=2977

 

Technorati Tags:

Live Writer

I have been using Live Writer for a while now and it is pretty good.  The latest version has some good improvements like a preview pane and the ability to see and work with the source.

Major gripe is that I can’t set a default font.  It keeps reverting to Verdana which I hate.

One issue I have seen is that when publishing it hangs occasionally and I lose the post. Not sure if its Live Writer or my broad band.  Quick fix is to always manually save a draft before publishing.  At least you don’t have to re-write if it goes wrong.

Overall I’m pretty happy with Live Writer.

 

Technorati Tags:

CTP 3 .NET 3.5 SP 1

Lesson number 1 – Read the Release Notes properly.

Went to use the new Out-GridvView cmdlet in CTP 3 and discovered that I needed .NET 3.5 SP1.  I knew from CTP 2 that I needed .NET 3.5 so didn’t really pick up on the SP1

Download and install it from here

http://www.microsoft.com/downloads/details.aspx?FamilyId=AB99342F-5D1A-413D-8319-81DA479AB0D7&displaylang=en

You will also need to see KB959209 at http://support.microsoft.com/kb/959209

and download the appropriate patches.

For Vista x86 download and install all 3 of the following updates  These updates should be installed in the following sequence:

Install the update for the .NET Framework 2.0 Service Pack 2 - Windows6.0-KB958481-x86.msu
Install the update for the .NET Framework 3.0 Service Pack 2 - Windows6.0-KB958483-x86.msu
Install the update for the .NET Framework 3.5 Service Pack 1 - NDP35SP1-KB958484-x86.exe

Might be a good time to try the new file transfer cmdlets

 

Technorati Tags: ,,

PowerShell Regular Expressions

I somehow ended up agreeing to do a session on Regular Expressions at an upcoming PowerShell UG meeting.  Not sure how it happened as RegEx is not my favourite topic.  I sort of started looking into it a while back but got distracted.

I was browsing round some of my blog links and it seems there has been an explosion of stuff about regular expressions so I thought I’d pull all of the links together.  Be useful when I get back to the beastly things.

In no particular order

http://bsonposh.com/archives/568  - has some good ideas for learning about regular expressions

http://bsonposh.com/archives/595good example of using them to investigate a routing table

http://blogs.microsoft.co.il/blogs/scriptfanatic/archive/2008/12/28/regular-expression-webcast-series.aspx – links to a webcast series with commentary

http://thepowershellguy.com/blogs/posh/archive/2008/12/29/regular-expressions-and-powershell-part-1.aspx – comments on the first parts of the webcast series

http://thepowershellguy.com/blogs/posh/archive/2008/12/30/monday-december-29-2008-5-16-pm-regular-expressions-and-powershell-part-2.aspx – includes link to a regex quick reference powershell function

Enjoy.  To paraphrase..   The code is out there.

 

PowerShell abolishes Christmas

I was experimenting, OK I was playing around, with dates and decided to put in Christmas Day

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

Oops PowerShell doesn’t allow Christmas!!

Blank look at the screen for a few moments before remembering that we have to use the US format for dates when we are entering them in PowerShell. If I want to enter a date eg 12th March 2009 I would instinctively write

PS> $dwrong = [datetime]"12/3/09"
PS> $dwrong

03 December 2009 00:00:00

And as you can see I would not get what I wanted.  What I need to enter is

PS> $dright = [datetime]"3/12/09"
PS> $dright

12 March 2009 00:00:00

And so Christmas becomes

PS> $xmas = [datetime]"12/25/09"
PS> $xmas

25 December 2009 00:00:00

Living in the UK dates are dd/mm/yyyy not mm/dd/yyyyy so this has been an issue I’ve tripped over a few times.  I had thought that it was a case of PowerShell not having had the bits done to allow other date formats but it turns out it is a design decision.

Lee Holmes has a really good post - http://www.leeholmes.com/blog/DateTimeCastsAreLanguagePrimitives.aspx – explaining the thinking behind the decision.

Having read it I now understand why I have to perform an un-natural act and put the month first.  Still find it awkward but I least I understand.

 

Technorati Tags: ,

PowerShell Homework

If you are just learning PowerShell and want to see how you are doing or you know PowerShell and want a problem to solve have a look at Jeffrey Hick’s Prof. PowerShell latest column at http://mcpmag.com/columns/article.asp?editorialsid=2963

 

Technorati Tags: ,