January 2009 - Posts

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.

Posted by Richard Siddaway's Blog
Filed under:

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

Posted by Richard Siddaway's Blog
Filed under:

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.

 

Posted by Richard Siddaway's Blog
Filed under:

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

 

Posted by Richard Siddaway's Blog
Filed under:

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:

Posted by Richard Siddaway's Blog
Filed under:

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:

Posted by Richard Siddaway's Blog
Filed under:

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

Posted by Richard Siddaway's Blog
Filed under:

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.

 

Posted by Richard Siddaway's Blog
Filed under:

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: ,
Posted by Richard Siddaway's Blog
Filed under:

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

Posted by Richard Siddaway's Blog
Filed under:

CTP3 – Advanced Functions

If you have been following the information released about CTP3 one of the things that will quickly become obvious is that something called Advanced Functions has been introduced. We now have functions and advanced functions in PowerShell.

For those of you who tried out CTP 2 you would have been aware of script cmdlets. Script cmdlets enabled cmdlets to be written in PowerShell rather than having to use C# and compile the cmdlet.

Advanced functions have replaced script cmdlets.

There is quite a lot to advanced functions so I am going to take a few posts to explore them fully.  We start by quickly reviewing PowerShell functions.

This is a function that I wrote a  long time ago when PowerShell was still in beta.

function Get-DiskFreeSpace
{
    Param ($computer=".")       #default to local machine

# get current foreground colour
    $origFg = $host.ui.rawui.foregroundColor     # get original foreground colour

#get the disk information
    $diskinfo = Get-WmiObject Win32_LogicalDisk -computer $computer

    Clear-Host
    if ($computer -ne ".")
    {
        Write-Host "Disk information for "  $computer  `n
    }
    else
    {
        Write-Host "Disk information for local host"  `n
    }

# set title line
    "{0,2}  {1,12}  {2,9}  {3,9}  {4,9}  {5,9} " -f "Drive", "Type", "Size",  "Used",  "Avail", "Use%"
    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
    }
    $host.ui.rawui.foregroundColor = $origFg   # reset foreground colour
}
set-alias df get-diskfreespace

This simply loops through the disks connected to the machine and displays the drive, the type, the size, space used, the space available and the percentage of usage.

We turn this onto an advanced function by  adding the [CmdletBinding] attribute.  Our function becomes

#Requires -Version 2.0
function Get-DiskFreeSpace
{
    [CmdletBinding()]
    Param ($computer=".")       #default to local machine

lots of stuff as before

}

The #Requires tells PowerShell that we have to be running on version 2.  If you try running on version 1 it will fail.

[CmdletBinding()] now defines that we have an advanced function that can be treated as a cmdlet.  What we can do with that & some of the other function enhancements we will see as we progress through rewriting this function to take advantage of the changes in PowerShell v2.  It is very important to note that the function as originally written still runs very happily in V2.

 

Posted by Richard Siddaway's Blog
Filed under:

PowerShell in Practice Ch8

Powershell in Practice Chapters 1-8 are now available for download under the Manning Early Access Program at  http://www.manning.com/siddaway/

Chapter 9 on DNS is nearly finished and will becoming to a download site near you shortly.

 

Technorati Tags: ,,,

Posted by Richard Siddaway's Blog
Filed under:

Password Policy

As I mentioned in an earlier post I am reading the Study Guide for the Exchange 2007 Design Exam (70-237).  There is quite a good section on security that goes beyond the normal Exchange stuff. In fact the book overall is good in that the topic coverage goes beyond the bare exam requirements.

One bit is glaringly, obviously wrong.

It states that in Windows 2008 the password policy can be linked at the site, domain or individual OU level.

No, No and thrice NO.

The password policy can only be linked, and be effective at the domain level.

The new Fine Grained Password Policies enable multiple password policies to be defined but they are linked to groups or individual users.

A full discussion on this topic together with PowerShell scripts to manage the policies is available from the April 2008 issue of Windows Administration in Realtime -

http://nexus.realtimepublishers.com/RTWA.htm

 

Error handling in PowerShell

Jeremy has made available the information from his talk yesterday at http://cid-39d7e872cb035259.spaces.live.com/blog/cns!39D7E872CB035259!123.entry

Enjoy

 

PowerShell User Group - today

Very odd evening for me.  There was a meeting of the UG that I’d organised but I couldn’t be there. I managed to connect via the Live Meeting but it felt really odd not being there.

Really big thank you to the speakers.  Jeffrey Snover gave an excellent overview of PowerShell v2 and some hints of where PowerShell is going. We will post the recording in the near future for those who couldn’t make the meeting.  Jeremy gave an excellent overview of error handling in PowerShell.  This will be on the recording as well. You need to look at this.  Error handling is not well understood and Jeremy gave an excellent run down of your options and what they mean.

Thanks to James, Stephen and everyone who covered for me at the meeting. I will be at the one in February.  A special thanks to everyone who turned up or joined the Live Meeting.

BTW – I’m not practicing an oscar acceptance speech  :-)

 

Technorati Tags: ,

PowerShell UG – February 10th

There is a PowerShell event being run by Microsoft in London on February 10th   http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!1936.entry.  We will be holding a PowerShell User Group meeting afterwards.

Main speaker is Jonathan Noble from Newcastle University - - http://jonoble.spaces.live.com/default.aspx

His talk is entitled - Hitting moving targets with PowerShell  - and describes how he uses PowerShell to manage the IT of a big University.  I know from talking to him that he is doing some very interesting stuff.

 

Technorati Tags: ,

CTP3 –PowerShell Jobs pt 2

We use start-job to create a new job.  I have found it best to supply a name so that the jobs can be tracked.  The other parameter is the PowerShell commands that will be run in the job.  If you want to run a script  use the –FilePath parameter to define its location

PS> Start-Job -Name j1 -ScriptBlock {get-process}

Id              Name            State       HasMoreData     Location             Command
--              ----                -----        -----------          --------                -------
1               j1                  Running    True                localhost            get-process

PS> Get-Job

Id              Name            State       HasMoreData     Location             Command
--              ----                -----        -----------          --------                -------
1               j1                  Running    True                localhost            get-process

Get-Job is used to view the progress. When the job has finished the status changes to completed.

PS> Get-Job

Id              Name            State          HasMoreData     Location             Command
--              ----                -----           -----------          --------                -------
1               j1                  Completed    True                localhost            get-process

We can retrieve the data using

Receive-Job -Name j1 -Keep

The –Keep parameter leaves the data in place.  If it is not specified the data is wiped from the job after display.

The job can be deleted from the queue by using

Remove-Job -Name j1

 

Technorati Tags: ,,

Posted by Richard Siddaway's Blog
Filed under:

CTP 3 - PowerShell Jobs

While a lot of the attention around CTP3 has been concentrated on remoting and some of the brand new functionality. One thing that seems to have been overlooked is the asynchronous jobs facility.  If you set a PowerShell task, be it script or from the prompt, you cannot do anything else in that session until the task finishes and you get the prompt returned to your control. Asynchronous, or background, jobs run in the background and immediately return the prompt for further work.

There are a bunch of cmdlets for working with jobs in PowerShell

Get-Job
Receive-Job
Remove-Job
Start-Job
Stop-Job
Wait-Job

If you have been using CTP 2 notice that the cmdlets have been renamed to *-Job from *-PSJob.

Also a number of cmdlets can be invoked directly as a job by using the –AsJob parameter

Invoke-Command
Invoke-WmiMethod
Test-Connection
Restart-Computer
Stop-Computer

The PowerShell remoting functionality needs to be enabled for jobs to work -  see http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!1985.entry

PowerShell also needs to be started with Administrator privileges. 

Next time we will look at how to use the *-Job cmdlets.

 

Technorati Tags: ,,

Posted by Richard Siddaway's Blog
Filed under:

Net start - -why?

I am reading the Exchange 2007 Design exam study guide at the moment.  The characters are a bit wooden and the plot is obvious but apart from that its not bad.

One bit made me think that the dots weren’t joined up though.  In a troubleshooting section the authors talk about stopping and starting a service.  When they show how to do it they use net stop and net start.

Hang on a minute.  This is Exchange 2007.  A pre-requisite is PowerShell 1.

PowerShell has good service support. It gets better in Version 2 but v1 has Stop-Service and Start-Service available through the EMS.    Grrr.  And they’d been doing a good job talking about PowerShell up to that point.

 

SQL Server scripts

Idera have published a set of PowerShell example scripts for working with SQL Server.  They can be downloaded (free) from www.idera.com   Check the bottom of the products menu for PowerShell scripts.

They give a good introduction to working with Powershell and SQL Server – recommended.

 

Technorati Tags: ,

More Posts Next page »