June 2009 - Posts

out-gridview

The version of PowerShell that ships with Windows 7 RC has fixed out-gridview so that we can display more than 10 columns.

try

get-process | select * | Out-GridView

to test it

Technorati Tags: ,
Posted by RichardSiddaway | with no comments
Filed under:

AD PowerShell on Windows 2008/2003 - supposedly

As James pointed out recently the AD Web Service from Windows 2008 R2 has been released for Windows 2008 and Windows 2003 -  see http://blogs.msdn.com/adpowershell/archive/2009/06/23/use-active-directory-powershell-to-manage-windows-2003-2008-dcs.aspx for details.

Having installed it there doesn’t appear to be any sign of the AD cmdlets or Provider.  On this basis it is useless.  If anyone knows different please let me know because I’ve looked in all the logical (and illogical) and I can’t find those cmdlets.  The Windows 2008 R2 RSAT won’t install so that source doesn’t work.

Microsoft Learning Manager

I went on to the Microsoft site looking for books on SQL Server 2008.  What you get is an incomprehensible jumble of stuff.  Don’t tell me about everything there is – let me get to the information I want.

I used to really like the Microsoft site as there was masses of information that usually logically arranged.  Now we get some many layers between us and the information that I’m likely to expire of old age (OK I know its not that long to go) before finding it. 

Another example – I went looking for the information on the SQL Server exams – the logical route through the site leaves you with the impression there isn’t an upgrade from SQL 2005 MCITP to the 2008 version.  Wrong! But oh how you have to search.

I’m coming to the conclusion that the only way to access the Microsoft site is to search from outside and hope you can get to what you need.

A triumph of style over substance at the moment.

Technorati Tags:
Posted by RichardSiddaway | with no comments
Filed under:

SQL Server autoclose

Buck Woody blogged about SQL Server autoclose and how it should be set to being off  - http://blogs.msdn.com/buckwoody/archive/2009/06/24/sql-server-best-practices-autoclose-should-be-off.aspx 

I’m doing a lot with SQL Server and PowerShell at the moment and it started me thinking that I could easily set this property in PowerShell.

001
002
003
004
005
006
007
008
009
010
$Server = New-Object Microsoft.SqlServer.Management.Smo.Server("SQL08")
$Server.databases | select Name, Autoclose
foreach ($db in $Server.Databases){
    if (!$db.IsSystemObject){
        $db.Autoclose = $false
        $db.Alter()
    }
}
$Server = New-Object Microsoft.SqlServer.Management.Smo.Server("SQL08")
$Server.databases | select Name, Autoclose

 

Create a server object and display the databases, selecting name and the autoclose property.  Its boolean so we get true or false back.

We can iterate through the database collection. Test if the database is a system database and set autoclose to false (we don’t want autoclose to happen).  A call to Alter() saves the change.

Finally we can recreate the server object and  redisplay the autoclose property.

Technorati Tags: ,
Posted by RichardSiddaway | with no comments

PowerShell survey

The PowerShell team want to know how you find PowerShell related material – scripts, training material etc etc

http://blogs.msdn.com/powershell/archive/2009/06/24/new-powershell-survey-on-connect.aspx

Technorati Tags:
Posted by RichardSiddaway | with no comments
Filed under:

foreach usage

I’ve noticed the way foreach is being used and it falls into two groups. I am using foreach-object to keep the discussion straight – like everyone else I use the foreach alias – yes I know I rant about aliases but the aliases for the *-object cmdlets make sense.

001
002
003
004
005
006
007
008
$things = Get-Content some_file.txt
foreach ($thing in $things){
    ## do stuff here
}

Get-Content some_file.txt | foreach-object{
    ## do stuff here
}

 

The first one reads the file and then iterates through the objects while second one reads the file and puts the objects on the pipeline.

So whats the difference and is it a big deal?  Instinctively I try to use the second but is that best?

using foreach we have to read the file and hold all the objects in memory while the foreach-object works with them one at a time as they come down the pipeline – for a big file that makes a lot of difference in resources.  However, if we need to access a file multiple times using foreach may be the better option as we only have to read the file once.  foreach can be faster which is a trade off we may need to think about

inside the loops we can use $thing or $_ to access the object respectively.  One point to think about is that if you do further work inside the loop that generates a different $_ eg a switch then reading the code may get confusing especially if you come back to it after a while

So is there a best option – probably not as an all time categorical “this is the best so always use it”

I tend to prefer the foreach-object as I can get on with processing objects straightaway though we do have to be careful with subsequent order of events sometimes.  The other advantage is that foreach-object gives me a –begin, –process and –end script block which makes things even more flexible

So no hard and fast answer but as a final thought the foreach-object usage looks more “powershelly” as someone once put it

Technorati Tags: ,
Posted by RichardSiddaway | 1 comment(s)
Filed under:

AD Recovery

I have always been impressed by by Quest’s AD Recovery Manager and now its even better – yep it has PowerShell cmdlets see http://wiki.powergui.org/index.php/Quest_Recovery_Manager_for_Active_Directory_cmdlets_reference

Posted by RichardSiddaway | with no comments
Filed under:

Scripting Games – Event 6 and 7

Event 6

Beginners – find the errors in the script

Advanced – read a text file of a network trace and find the delay

can’t be bothered. 

Beginners was done last year plus I really hate scripts that have $objxxx    - so VBScript 

Advanced is yet another variation on reading a file.

Event 7

Advanced – write a script to play 21 or blackjack or pontoon or whatever you want to call it.  Did that last year see http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!1161.entry

Might have a look at beginners 7

Technorati Tags:
Posted by RichardSiddaway | with no comments
Filed under:

PowerShell in Practice Chapter 13

Chapter 13 – IIS – is now available on MEAP  www.manning.com/siddaway

Technorati Tags:
Posted by RichardSiddaway | with no comments
Filed under:

Games: Advanced 4

Read a file and create a graph of the results.  The quickest way to graph the data is to take the height and display a number of “*” depending on the value.

001
002
003
004
005
006
007
008
cls
Get-content "High Jump Stats_Adv4.txt" | foreach {
    $data = $_ -split ","
    Write-Host "Jumper: $($data[1]) $($data[0]) last $($data.count - 3) jumps"
    for ($i=2;$i -le $($data.count - 1); $i++) {
        "*" * $data[$i]
    }
}

 

-split is a PowerShell 2 operator -  use $_.Split(“,”) in v1

BTW – there are 43 jumps per person not the 30 as stated in the event information.

This answers the letter of the event but probably not the spirit. PowerGadgets would be an interesting option for this.  PowerGadgets installs straight into Windows 7. I had tested it with PowerShell v2 in the past but nice that it installs on Windows 7.

If we want to create individual graphs using PowerGadgets

001
002
003
004
005
cls
Get-content "High Jump Stats_Adv4.txt" | foreach {
    $data = $_ -split ",",3
    $data[2] -split "," | out-chart -gallery lines -Title "$($data[1]) $($data[0])"   
}

 

All we do is pipe numeric data (notice the double split – the first gives the names plus the numbers as one string.  We can then split the numbers separately as required) into out-chart using the first two elements from the first split (jumpers name) as the title.

Finally lets look at charting in Excel – we have to use the COM object to work with Excel (wouldn’t be nice if we got proper PowerShell support in next version of Office – please -  )

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
cls
$sfile = "C:\Scripts\Scripting Games 2009\Competitors pack\ad4.xlsx"
if(Test-Path $sfile){Remove-Item $sfile}


## create a spreadsheet
$xl = New-Object -comobject "Excel.Application"
$xl.visible = $true
$xlbooks =$xl.workbooks
## remember non-US culture
## add work book
$newci = [System.Globalization.CultureInfo]"en-US"
$wkbk = $xlbooks.PSBase.GetType().InvokeMember("Add", `
     [Reflection.BindingFlags]::InvokeMethod, $null, $xlbooks, $null, $newci)

$sheet = $wkbk.WorkSheets.Item(1)
$sheet.Name = "High Jump"

## read the file
$row = $col = 1
Get-content "High Jump Stats_Adv4.txt" | foreach {
    $data = $_ -split ",",3
    $numbers = $data[2] -split ","
    ## name
    $sheet.Cells.Item($row, $col) = $data[1]
    $sheet.Cells.Item($row, $col+1) = $data[0]
    ## jumps
    for ($i=0;$i -le $numbers.length-1;$i++){
        $sheet.Cells.Item($row, $col+2+$i) = $numbers[$i]
    }
    $row++
}

## get the cell range
$xl.Charts.Add() | out-null
$xl.ActiveChart.chartType = 4  ## line chart

$xl.ActiveChart.HasTitle = $true
$xl.ActiveChart.ChartTitle.Text = "High Jump Results"

## (x axis =1, y axis = 2)
$xl.ActiveChart.Axes(1, 1).HasTitle = $true
$xl.ActiveChart.Axes(1, 1).AxisTitle.Text = "Attempt"
$xl.ActiveChart.Axes(2, 1).HasTitle = $true
$xl.ActiveChart.Axes(2, 1).AxisTitle.Text = "Height"

[void]$wkbk.PSBase.GetType().InvokeMember("SaveAs", `
   [Reflection.BindingFlags]::InvokeMethod, $null, $wkbk, $sfile, $newci)

[void]$wkbk.PSBase.GetType().InvokeMember("Close", `
   [Reflection.BindingFlags]::InvokeMethod, $null, $wkbk, 0, $newci)

$xl.Quit()

 

We create a spreadsheet and add a work book .  Have to use this long winded method as I am using a non-US culture on my machine (Excel bug).

We can add the work sheet, add the data and finally add the chart.  Chart looks ugly but it is a chart.  Finally save the spreadsheet using the same horrible construction. 

didn’t like this event - tedious

Posted by RichardSiddaway | with no comments
Filed under:

Games: Advanced 5

In this event we have to pull some information out of the properties of some photos.  This information isn’t in the normal properties. We need to load the drawing classes to access the data.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
#http://blogs.technet.com/jamesone/archive/2007/07/13/exploring-photographic-exif-data-using-powershell-of-course.aspx
function ConvertTo-Chars {
param ($bytedata)
    $str = ""
    for ($i=0; $i -le $bytedata.Length-1;$i++){
        $str = $str + [char]$bytedata[$i]
    }
    Return $str
}
cls
[reflection.assembly]::loadfile( "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll") | out-null
"{0,-12} {1,-20} {2,-6} {3,-12}" -f  "Name", "Date Taken", "Make", "Model" 
Get-ChildItem *.jpg | foreach {
   $photo = New-Object -TypeName system.drawing.bitmap -ArgumentList $($_.FullName)
   $dts =  (ConvertTo-Chars $photo.GetPropertyItem(36867).value) -split " "
   $ds  = $dts[0] -split ":"
   $date = "{0}/{1}/{2} {3}" -f $($ds[2]), $($ds[1]), $($ds[0]), $($dts[1]) 
   $maker = ConvertTo-Chars $photo.GetPropertyItem(271).value
   $model = ConvertTo-Chars $photo.GetPropertyItem(272).value
   "{0,-12} {1,-20} {2,-6} {3,-12}" -f  $($_.Name), $date, $maker, $model 

}

 

Use –f to create a formatted string as a header.

Loop through the photos and create a bitmap object for the photo. The properties are held in a number of formats – they are explained in James’ blog that is commented in the beginning of the script. Luckily the ones we want are strings – but are held as byte arrays.

The camera maker and model are simply passed into the function that we use convert to a string.  The date we convert and then re-arrange from yyyy-mm-dd to dd/mm/yyyy format. We can then create a formatted script to display the data.

Technorati Tags: ,
Posted by RichardSiddaway | with no comments
Filed under:

Games: Beginner 5

This one involves setting some registry settings to increase the number of concurrent downloads.  I’m running Windows 7 and IE 8 which have already increased the limits from 2 to 6. Tobias has done a really good job on his expert commentary - http://blogs.technet.com/heyscriptingguy/archive/2009/06/18/hey-scripting-guy-event-5-solutions-from-expert-commentators-beginner-and-advanced-the-400-meter-race.aspx - so rather than repeat that I’m going to use this as an example of using transactions in PowerShell v2.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
#Requires -version 2.0
#IE 8 increases limit to 6 from 2
#need to create keys
cls
cd "HKCU:\Software\Microsoft\Windows\CurrentVersion"
"Before"
Get-ItemProperty "Internet Settings"

Start-Transaction

New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" `  
 -Name MaxConnectionsPerServer -PropertyType DWORD -Value 10 -UseTransaction   | Out-Null
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" `
 -Name MaxConnectionsPer1_0Server  -PropertyType DWORD -Value 10  -UseTransaction | Out-Null

"During"
Get-ItemProperty "Internet Settings" -UseTransaction

Read-Host "Continue"
Undo-Transaction

"After"
Get-ItemProperty "Internet Settings" 

cd \
cd c:

 

Use Requires to restrict to PowerShell v2

use the registry provider to navigate to the location of the settings and use get-itemproperty to display the values

We can then start our transaction. Make the changes and display the properties again.  Notice that we have to use the

-UseTransaction parameter to involve these cmdlets in the transaction.  A Read-Host is used to pause the script.  Check the values and we can seen that the properties have been added.  Continue the script by pressing any key (if you can find it)  and then the transaction will undo.  Display the properties again to show that the change has been undone.

Transactions are only available on the Registry provider at the moment.  Hopefully, they will be extended onto the other providers in the next version of PowerShell.

Posted by RichardSiddaway | with no comments
Filed under:

The incredible shrinking URL

Some urls on the web become a real pain to type because of their length.  Tinyurl, and other similar services, can be used to shrink the url to a much more manageable length.

Joe Pruitt has a PowerShell script to perform the shrinking – find it here http://devcentral.f5.com/weblogs/Joe/archive/2009/06/19/shrink-url-ndash-use-powershell-to-shrink-your-urls.aspx

Technorati Tags: ,
Posted by RichardSiddaway | with no comments
Filed under:

Games: Advanced 3

This one involves reading a text file, finding all the words that use a single vowel (may have multiple instances of that vowel e.g. look) and write them out to a text file.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
## find the univowel words
## - 1 or more instances of the same vowel
## - all vowels the same
if (Test-Path univowel.txt){Remove-Item  univowel.txt}
Get-Content Wordlist_ADV3.txt | foreach {
    $y = 0
    $z = $_.ToCharArray()
    if ($z -contains "a") {$y++}
    if ($z -contains "e") {$y++}
    if ($z -contains "i") {$y++}
    if ($z -contains "o") {$y++}
    if ($z -contains "u") {$y++}
    if ($_ -eq "look"){"$_ $y"}
    if ($y -eq 1){Add-Content -Path univowel.txt -Value $($_)}
}

 

Delete the answer file if it exists.  Read the file & loop through the contents. Quick & dirty brute force approach for this one.  Convert the work to a character array and use contains to check for vowel membership – only 5 vowels so 5 if statements. Tried a switch but it counts each each instance so wrecks the result ie didn’t accept “look”.  For each hit increment the counter ($y).

At the end if $y = 1 it means we have only one vowel in the word so write it to the text file.

Not a task I need to do very often but it works.

Technorati Tags: ,
Posted by RichardSiddaway | with no comments
Filed under:

Kill the Messenger

I’ve mentioned before that I find the way that the latest incarnation of Messenger on Windows 7 keeps starting whenever I access any other Live product.  Finally got annoyed enough to make a kill messenger icon.

Create a shortcut on your desktop for the PowerShell exe and then change the target string (on Shortcut tab) to "%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe " -NoProfile -Nologo -Command  &"{Get-Process msnmsgr | Stop-Process}"

This starts up PowerShell without the profile and logo and immediately runs the command Get-Process msnmsgr | Stop-Process which terminates with extreme prejudice any instances of messenger.   On the same tab I also set the Run drop down to Minimized so I don’t get the full flash of PowerShell starting and shutting.

Messenger: you can start but you can’t run

Technorati Tags: ,
Posted by RichardSiddaway | with no comments
Filed under:

Virtual Conference

Don’t forget the TechNet virtual conference tomorrow (19th June).  There have been a lot of registrations for this – but we can squeeze a few more in at the back.

 

Posted by RichardSiddaway | with no comments
Filed under:

Games: Beginner 3

We start with a file and have to put the first paragraph into one file and the second into another file. 

001
002
003
004
005
006
007
008
009
010
$flag = $true
if (Test-Path "Shot Put A.txt"){Remove-Item "Shot Put A.txt"}
if (Test-Path "Shot Put B.txt"){Remove-Item "Shot Put B.txt"}
Get-Content "Shot Put.txt" | foreach {
    if ($_ -ne ""){
        if ($flag){Add-Content -Path "Shot Put A.txt" -Value $($_) }
        else {Add-Content -Path "Shot Put B.txt" -Value $($_)}
    }
    else {$flag = $false}
}

 

Create a flag (set true). Test for the existence of the output files and delete if present   Read the file and loop through.  We can identify the paragraph break as there is an empty line – when we get to that we change the value of the flag.  If the flag is true add the line to the first file otherwise add to the second file.

 

Technorati Tags: ,
Posted by RichardSiddaway | with no comments
Filed under:

Games: Advanced 2

This is playing in a spreadsheet.  Need to do some calculations and sorting

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
$header =  1   ## yes it does. 0 = no header
$asc  = 1      ## sort ascending
$desc = 2      ## sort descending

$xl = New-Object -comobject "Excel.Application"
$xl.visible = $true
$wkbk = $xl.WorkBooks.Open("C:\Scripts\Scripting Games 2009\Competitors pack\LongJump_Adv2.xls")
## $wkbk.workSheets | Format-Table Index, Name -AutoSize
$sheet = $wkbk.WorkSheets.Item(1)

$sheet.Cells.Item(1,10).FormulaLocal = "Ratio"

for ($i=2;$i -le 19; $i++){

## calculate score
$formula = "=max(e$i" + ":" + "g$i)"
$sheet.Cells.Item($i,8).FormulaLocal = $formula

## over or under achieving
$achieve = "=IF(H$i" + ">D" + $i + ',"Exceed",IF(H' + $i + "<D" + $i + ',"Under Perform","Achieve"))'
$sheet.Cells.Item($i,9).FormulaLocal = $achieve

## ratio over best
$ratio = "=(H" + $i + "/D" + $i + ")"
$sheet.Cells.Item($i,10).FormulaLocal = $ratio
}
## find the winner
$range = $sheet.UsedRange
$range1 = $xl.Range("H2")
$range.Sort($range1, $desc) | Out-Null
Write-Host "The winner is $($sheet.Cells.Item(2,1).FormulaLocal) `
             of $($sheet.Cells.Item(2,2).FormulaLocal) `
             with a jump of $($sheet.Cells.Item(2,8).Text)"

## sort the sheet by achievement
$range1 = $xl.Range("J2")
$range.Sort($range1, $desc) | Out-Null

 

Some constants are defined at the beginning and then we open the spreadsheet.  Add a header to an extra column we will be using (11) .  We can then loop through each row finding the maximum of the scores and putting it into the results column (17) In the same loop we can determine if they are exceeding their season best (21) and calculate a ratio (25)

A sort on the results column means we can pick off the winner (31) and then another sorts leaves the spreadsheet ordered by the comparison to the season best.  It can be saved like that if required.

Interesting mix of PowerShell and Excel but the challenges are in the Excel side and how to get that working in PowerShell rather than PowerShell itself.  One possibility would be to open the spreadsheet and create a csv file which would make some the work easier but its probably not worth the effort.

Technorati Tags: ,
Posted by RichardSiddaway | with no comments
Filed under:

Games: Beginner 2

In this one we need to use WMI to get some information about the Processor in our machine.  Main difficulty is finding which class. In PowerShell v2 I can get away with this

Get-WmiObject -List "*processor*"

whereas in v1 I need to use

Get-WmiObject -List | where{$_.Name -like "*processor*"}

In either case the Win32_Processor class looks to be the best choice.   This leads to

001
002
003
004
005
006
007
$machine = Get-WmiObject -Class Win32_Processor
"Speed"
$machine | Format-List MaxClockSpeed, L2CacheSize, L2CacheSpeed, L3CacheSize, L3CacheSpeed
"Strength"
$machine | Format-List NumberOfCores, NumberOfLogicalProcessors
"Agility"
$machine | Format-List AddressWidth

 

Get the WMI information once and then select the bits we want to meet the criteria

Get-WmiObject -Class Win32_Processor | Get-Member

will give a full list of the properties.

If you want to colour the output use write-host and pick off the properties individually

Technorati Tags: ,
Posted by RichardSiddaway | with no comments
Filed under:
More Posts Next page »