Today is my last day at Microsoft after 10 years, it’s sad to be going, but as someone said once “Regrets. I’ve had a few, but then again too few to mention.” I’ve met some great people while I’ve been here and I look back on my time here with more pleasure than regret.
That’s the end for this blog. My new blogs is at http://jamesOne111.wordpress.com. If you’ve found what I had to say interesting, update your bookmarks.
James.
In my previous post I was talking in general terms about why BPOS was a sound idea. The recent announcement of Ray Ozzie’s retirement set people quoting his mantra “Three screens and a cloud” – the three screens being Computer, Mobile device, and TV. The unwritten part of “Three screens” is recognising their diversity: people should interact with the best possible client – which means adapting to the specifics of each “screen”; it’s not “any browser and a cloud”: many phone apps do something which PCs do in the browser, they only exist because of the need to give a different experience on a different kind of screen. Instead of seeing a monolithic website (which in reality probably wasn’t monolithic) we see an app which consumes a service (probably the same service which was behind the web site).
But there was more than publishing stuff using services instead of HTML pages; more even than the likes of Groove or Live Meeting which used the cloud to enable new things. From Ozzie’s vision, famously expressed in 2005, came a realization that services already used by business PCs and devices would increasingly be in the cloud, instead of on an organizations own servers. That was the cue to provide Exchange as a service, SharePoint as a service and so on. We’ve tried to make a distinction between “Software as a Service” – which in some people’s minds is “Any browser and a cloud” and “Software PLUS Services” – which covers a plethora of client software: from multi-player games on Xbox to iTunes to Outlook talking to an Exchange server. But when Office Outlook on a PC accesses Exchange-Online , Exchange is software and it is provided as a service –it just isn’t accessed using a browser: I haven’t yet seen a successful way to make the distinction between the two kinds of “Software as a service” just understand it has different meanings depending on who is speaking.
I don’t know if it was planned but it seemed fitting that we should announce the next generation of BPOS on the day after Ray’s announcement. I prefer the new name Office 365. Mary Jo Foley posted something headed “This is not Office in the cloud” – in which she says “this was not some out-of-the-blue change in Microsoft’s business model. Microsoft is still pushing Office first and foremost as a PC-based software package.” Which is spot on: if you need office in a browser, Office Web App is there but it is not a replacement. I wrote in the previous post about the challenges of providing SharePoint, Exchange and so on, it is not Office but the services behind Office which are in the cloud. The key points of Office 365 are these:
I think the a-la-carte pricing option is a good thing – though some are bound to say “Microsoft are offering too many options”. The plans are just the combinations of cloud services we think will be popular; services can be added to a plan or bought standalone – for example “Kiosk” workers can get on the company e-mail system with Outlook web access from $2. We’ve announced that the plans will cost between $4 to $27 per month, that one of the enterprise plans closely mirrors the current BPOS at the same $10/user/month, and that there will be $6 plan with the features we think small business will need. In the run up to the launch I did see some details of different plans and options but I haven’t seen all of these in the announcements and it is not impossible that they will be fine tuned before the system goes fully live. When will that be? The launch has a beta programme (sign-up is at http://office365.microsoft.com) , Mary-Jo said back in July that the plan was for full launch was early 2011 which sounds about right – it’s also necessarily vague, because a beta might reveal a lot of unexpected work to be done: if you want a more precise date I always say in these cases those who know won’t talk, and those who talk don’t know.
We’ve positioned Office 365 as helping small businesses to think big and big business to act fast – the link gives examples which range from the Starwood hotel chain to a single independent restaurant – it’s worth taking time to work out what it might mean to the organization(s) you work in/with: the cloud might be right for you, it might not - but if it isn’t I’d want to be able to explain why not and not have people think an opportunity was being missed through inertia.
This post now appears on my new blog (http://jamesone111.wordpress.com ) - James O’Neill’s blog Thinking about the cloud Part 2 office 365
I was telling someone recently that before I joined Microsoft I spent the late 1990s running a small training company. The number of employees varied, averaging out at a dozen or so. I delivered training, did the business management, helped the win over customers and I looked after the IT. It was like doing two or three jobs.
I’ve been quite reticent about our “Business Productivity Online Service"partly because it takes a long and closely argued post to cover why, from an IT professional’s point of view, getting rid of your servers isn’t abdicating. (This is not going to be that post). But as chance would have it I was looking at BPOS again with my old job in my thoughts. B-POS sounds like it should be something… ”points of sale”, but it is Exchange,Communications server and Sharepoint provided as Pay-monthly “Cloud services”
In the training company we ran all our own IT services, but there’s no way I’d host my own web-server today: the sense of using a hosting company was clear before I left for Microsoft. The launch of BPOS gave businesses a way to get hosted Mail (Exchange), Presence & IM (OCS) and Collaboration & Document management (Sharepoint) for $10 US per month – or in round numbers £80 annually - per user. Comparing that with the cost of server hardware and software and especially the time that in-house systems took up, if I were running that business today, my head would say get rid of the servers. You can mix in-house and in-cloud servers; users keep the same desktop software which is crucial: you don’t give up Outlook to move your mailboxes to the cloud.
It needs a change of attitude to give up the server. If my head argued costs and figures, my heart might have come back with benefits like “You are master of your own destiny with the servers in-house”. But are you ? Back then we couldn’t justify clustering our servers, so if hardware failed – work would stop until it was repaired. Paying for a service in a Microsoft datacentre means it runs on clustered hardware, which someone else maintains. Microsoft’s datacentre is a bigger target for attack, but the sheer scale of the operation allows investment in tiers of defence. Small businesses tend not to worry about these things until something goes wrong, and you can always tell yourself that the risk is OK if you’re getting a better service in-house. But the truth is you’re probably not getting better service. As a Microsoft employee I’m used to having access to my mail and calendar from anything that connect to the internet – laptop at home, or on the move, any PC with web access, or Sync’d to a phone. I doubt if I would have set that up for the training company but it’s part of BPOS – even to the extent of supporting iPhones and Blackberries. Getting rid of servers could not only save money but give users a better set of tools to use in their jobs – an easier thing to accept now that I don’t run servers for a business.
Now if you’ve come across the idea of the HypeCycle (see Wikipedia if not) – I agree with Gartner that cloud technologies somewhere near “peak of inflated expectations” - in other words people are talking up “the cloud” beyond it’s true capabilities, and if things follow a normal course there will be a “trough of disillusionment” before things find their true level. I don’t buy into the idea that in the future scarcely any business will bother with keeping their own server, any more than they would generate their own electricity. Nor do I buy into the polar opposite - that very few organisations, and none with any sense, will keep critical services in the cloud – that idea seems just as implausible to me. So the truth must lie in between: the method of delivering services to users won’t change from one foregone conclusion (the in-house server) to another foregone conclusion (the service in the cloud), like so many things it will be a question of businesses asking “does it make sense to do this in-house”, and I think IT professionals will want to avoid depending on that question being answered one way.
This post appears on my new blog (http://jamesone111.wordpress.com )- James O'Neill's blog Thinking about the cloud (part 1).
My phone rang: it was my dad. Father/son combinations don’t ring to chat like mother/daughter ones do, and Dad had been having computer problems. Specifically, Excel had been crashing but managing to recover his work. Each time it had offered to send data to Microsoft and each time he had declined. Then his phone had rung and the caller said it was about the problems he was having problems with his computer.
To me this was immediately suspicious, there is nothing in the Microsoft reporting process which sends personal information like phone-numbers. In fact when you register Windows you don’t put a phone number in, and it is not stored anywhere in the configuration of the machine. Dad doesn’t have a support contract with anyone so even if personal information were being sent I wouldn’t expect a phone call. It would need quite some call centre to manage a courtesy call every time an app crashed. The only way the caller could know that there was a problem and have his details was if something malign on the machine was telling them. Dad assumed the caller was legitimate: he assumed they’d been given his details by Microsoft, we only give your personal information to a 3rd party if you have requested a specific service which needs us to do that, or said you were happy to be called about something specific by a partner (which is Opt-in, not opt-out). They had his confidence and things now went from bad to worse, the caller got Dad to give him remote access to the PC for 50 minutes. There’s no telling what went on in that time, but at this stage I had to assume his machine could be doing anything and everything on it machine was potentially compromised. Changing passwords would do no good if a key-logger had been installed. After 50 minutes they called back and told Dad they’d removed 300 viruses from his machine (A bit of a dent for the Anti-virus software he was using, and almost certainly untrue) and signed him up for a £180 support contract which he paid by credit card. When he went to use the card… as if you couldn’t guess, it bounced.
I told him to turn everything off and quarantine the PC. Having realised he’d been taken in, he took steps to get his credit card re-issued, and he set about changing all the passwords which might have been exposed on this machine -using a different one. He’d heard about someone whose stock portfolio had been compromised: the crook had changed address and bank details and it was only when they tried to sell everything, that the broker’s system spotted something might be wrong. I had to visit, and
My father was a smart man – smarter than me if I’m honest – and although he has been retired for nearly 20 years I don’t think he has lost his wits. I spent the afternoon of that phone call moving between rage and incomprehension – how could he be so stupid. (Many readers will know the famous “Word Perfect support call ” story – put that into Bing or Google if you don’t: it ends with "unplug your system and pack it up just like it was when you got it. Then take it back to the store you bought it from." “What do I tell them?" "Tell them you're too stupid to own a computer." ) . The problem is – of course – that confidence tricksters are plausible, and anyone can fall for social engineering if it is well enough done.
It turns out that this is a scam being used by a couple of firms in India – they don’t get malware onto the machine and then call to fix it; they randomly call people and tell them they have a problem. It was a company using the name of OnlinePcCare.com who scammed my Dad . One interesting thing was they put the credit card transaction through a third party G2S.com, and it may be that which triggered a fraud alert, the credit card company wouldn’t say. A search on Bing for “onlinePcCare +scam” finds plenty of other victims or near misses. This one from Ireland was immediately familiar “can you start event viewer… are there any errors in the application log ?”. If the event log is empty, logging itself is broken. Some people recorded the scammers and have posted the call to you-tube – these come near the top in a search and Digital toast has a selection – together with a list of other names used by these people.
Charles Arthur at The Guardian has been covering this story for a little while, see Police crack down on computer support phone scam, and Virus phone scam being run from call centres in India. His blog post Those 'PC virus' phone call scams: the unanswered questions is a worth reading too; it confirms my finding that no malware seems to get installed, and shares my opinion that this fits the definition of obtaining money by deception. (Dad’s call to the police got a response of “here’s a crime number – we’ve got a big file on this and we’ll add you to it”)
If you act as family tech support, do yourselves a favour. As well as pointing out that none of those nice men in Nigeria will really have a fortune which they will share, and that it is statistically nearly impossible to have a large lottery win and at the same time be unaware of entering the draw, now you need to add “no one really knows if you have a problem with your computer and calls to fix it” (you may be yelling at the computer but in cyberspace no-one can hear you scream.)
You might add “If you don’t like unsolicited calls register with the telephone preference service, no reputable company will call you once you’ve registered and any company which does call you is, by definition, not reputable
Postscript. While I was working on this post I got a call from OnlinePcCare. It may be one of those random things or they may be stepping up their activities.
This post appears on my new blog ( http://jamesone111.wordpress.com/ ) - James O'Neill's blog An unexpected call from a help desk? Hang up.
In Part one I showed how my downloadable PowerShell module can tag photos using related data – like GPS position – which was logged as they were being taken, and in part two I showed how I’d extended the module in James Brundage’s PowerPack for Windows 7. Now I want to explain the extensions which automate the processes of:
The data and pictures are connected by the time stamp on each, but to connect properly the scripts must cope with any time difference between the camera’s clock and time on the logging device – whether that’s a GPS unit or my wrist mounted scuba computer. A few seconds won’t introduce much error, but the devices might be in different time zones –for example GPS works on Universal time (GMT) - so the offset is often hours, not seconds. My quick and dirty way of making a note of the difference is to photograph whatever is doing the logging (assuming it can display its time). The camera will record the time its own clock was set to in the EXIF “Date and time taken” field and subtracting that from the time displayed on the logger in the picture gives an offset to apply to all data points. The following is the core of a function named Set-Offset which could be seen in part one;
Set-Offset
$RefDate = ([datetime]( Read-Host ("Please enter the Date & time " + "in the reference picture, formatted as" + [char]13 + [Char]10 + "Either MM/DD/yyyy HH:MM:SS ±Z or " + "dd MMMM yyyy HH:mm:ss ±Z")) ).touniversalTime() $ReferenceImagePath = Read-Host "Please enter the path to the picture" if ($ReferenceImagePath -and (test-path $ReferenceImagePath) -and $RefDate) { $picTime = (get-exif -image $ReferenceImagePath).dateTaken $Global:offset = ($picTime - $refdate).totalSeconds }
$RefDate = ([datetime]( Read-Host ("Please enter the Date & time " + "in the reference picture, formatted as" + [char]13 + [Char]10 + "Either MM/DD/yyyy HH:MM:SS ±Z or " + "dd MMMM yyyy HH:mm:ss ±Z")) ).touniversalTime()
$ReferenceImagePath = Read-Host "Please enter the path to the picture" if ($ReferenceImagePath -and (test-path $ReferenceImagePath) -and $RefDate) { $picTime = (get-exif -image $ReferenceImagePath).dateTaken $Global:offset = ($picTime - $refdate).totalSeconds }
The real Set-Offset can take –refDate and –ReferenceImagePath parameters so the user doesn’t need to be prompted for them. Most of code you can see is concerned with getting the user to enter the time (in a format that PowerShell can use) and the path to the file. The only part which uses the image module is (get-exif -image $ReferenceImagePath).dateTaken Get-Exif is a command I added, and it returns an object which contains all the interesting EXIF data from the image file. Only the value in the DateTaken property is of interest here; it is used to calculate the number of seconds between the camera time and logger time and the result is stored in a global variable named $offset.
–refDate
–ReferenceImagePath
(get-exif -image $ReferenceImagePath).dateTaken
Get-Exif
DateTaken
$offset
The next step is to read the data and applying the offset to it; depending on the how it was logged the next step will be either: $Points = Get-NMEAData -Path $Logpath -offset $offset Or $Points = Get-GPXData -Path $Logpath -offset $offset Or $Points = Get-CSVGPSData -Path $Logpath -offset $offset Or $Points = Get-SuuntoData -Path $Logpath -offset $offset
$Points = Get-NMEAData -Path $Logpath -offset $offset Or $Points = Get-GPXData -Path $Logpath -offset $offset Or $Points = Get-CSVGPSData -Path $Logpath -offset $offset Or $Points = Get-SuuntoData -Path $Logpath -offset $offset
$Points = Get-GPXData -Path $Logpath -offset $offset
$Points = Get-CSVGPSData -Path $Logpath -offset $offset
$Points = Get-SuuntoData -Path $Logpath -offset $offset
The last one handles the comma separated data exported from the Suunto Dive Manager program which downloads the data from my dive watch. The other 3 deal with different formats of GPS data, it may be in the form of NMEA sentences (comma separated again) or the CSV format used by Efficasoft GPS utilities on my phone or the XML-based GPX format. (GPS data formats are worth another post of their own). You may need to make slight alterations to these functions to work with your own logger, but they are easy to change. All of them except Get-GPXdata import from a CSV file – and use a feature which is new in PowerShell V2 to specify the CSV column headings when using the import-csv command. Get-GPXData uses XML documents looking for a hierarchy which goes <gpx> <trk> <trkseg><trkpt><trkpt><trkpt><trkpt>… All the functions use select-object to remove fields which aren’t needed and insert calculated data (for example converting the native speed in knots from GPS to MPH and KM/H )
Get-GPXdata
import-csv
Get-GPXData
<gpx> <trk> <trkseg><trkpt><trkpt><trkpt><trkpt>…
select-object
After running one of these commands there will be a collection of data points stored in the variable $points. Each data point has a time – adjusted by the offset value, so it is time as the camera would have seen it. The Suunto dive computer points have a Description (the name of the dive site and water temperature) and depth, while the GPS points have Speed (GPS works in knots and the script calculates Miles per Hour and Kilometres per hour); bearing, latitude as Degrees, Minutes, Seconds, North or South, Longitude as Degrees, Minutes, Seconds East or West, Latitude & Longitude in their original form from the logger and Altitude in both meters and Feet (NMEA data needs extra processing to get the attitude data and Get-NMEAdata has a –NoAltitude switch to allow processing to be speeded up if it only Latitude and Longitude are needed )
$points
Get-NMEAdata
–NoAltitude
Armed with a collection of points the next step find the one nearest to the time the picture was taken; a function named Get-NearestPoint does this. Given the time stamped on the photo the function returns the data point logged closest to that time. It isn’t very sophisticated, taking 3 parameters: a time, a time-sorted array of points and the name of field on the data points to check for the time, and working through the points until the point being looked at is further away from the target time than the previous point; the core of the function looks like this:
Get-NearestPoint
$variance = [math]::Abs(($dataPoints[0].$columnName - $MatchingTime).totalseconds) $i = 1 do { $v = [math]::Abs(($dataPoints[$i].$columnName - $MatchingTime).totalseconds) if ($v -le $variance) {$i ++ ; $variance = $v } } while (($v -eq $variance) -and ($i -lt $datapoints.count)) $datapoints[($i -1)]
In use it looks something like this.
$image = Get-Image –Path "MyPicture.Jpg" $dt = Get-ExifItem -image $image -ExifID $ExifIDDateTimeTaken $point = Get-nearestPoint –Data $points -Column "DateTime" -MatchingTime $dt
$point contains the data used to set the EXIF properties of the picture, a process which requires a series of Exif filters to be created – and I explained EXIF Filters in Part 2. As well as data retrieved from a log, there are times when I want to tag a picture manually. For example I took some photos in London’s Trafalgar Square without a GPS logger that I want to tag with 51°30’30” N, 0° 7’40” W . To make this easier I created a function named Convert-GPStoEXIFFilter which can be invoked like this:
$point
Convert-GPStoEXIFFilter
$filter = Convert-GPStoEXIFFilter 51,30,30 "N" 0,7,40 "W"
If you’re not used to PowerShell I should say that in some places 51,30,30 would be the way to write 3 parameters. In PowerShell it is one array parameter with 3 members. (Even old hands at Powershell occasionally get confused and put in a comma which turns two parameters into a single array parameter) I could have explicitly named the parameters and made it clear that these 3 were an array by writing -LatDMS @(51,30,30) -NS "N"
-LatDMS @(51,30,30) -NS "N"
Convert-GPStoEXIFFilter returns a chain of up to 7 EXIF Filters for GPS version, Latitude reference (North or South) Longitude reference (East or West), Altitude reference (above or below Sea Level), the Latitude & Longitude (as degrees, Minutes, Second and Decimals) and Altitude in meters (altitude is optional). If $point holds the data logged at the time the picture was taken Convert-GPStoEXIFFilter can be invoked like this:
$filter = Convert-GPStoEXIFFilter -LatDMS $point.Latdms -NS $point.NS ` -LONDMS $point.londms -EW $point.ew -AltM $point.altM
At the end of part 2 I showed the Copy-Image command that handles renaming, rotating, and setting keywords & title EXIF fields and mentioned it could be handed a set of filters. All the parameters that Copy-image uses are available to Copy-GPSImage, which takes the the set of points as well . Internally it performs the $image= , $dt= , $point= and $filter= commands seen above before calling Copy-image with the image, the filter chain and the other parameters it was passed. The full set of parameters for Copy-GPSImage is as follows
Copy-Image
Copy-image
Copy-GPSImage,
$image=
$dt=
$point=
$filter=
Copy-GPSImage
Two values separated by a comma specifying a replacement in the file NAME
If specified returns the point(s) matched with the pictures
So now it is possible to use three commands to geotag the images, the first two get time offset , and get the data points, applying that offset in the process.
set-offset "D:\dcim \100Pentx\IMG43272.JPG" –Verbose $points= Get-CSVGPSData 'F:\My Documents\My GPS\Track Log\20100425115503.log' ‑offset $offset
and the third gets the files on a memory card and push them into Copy-GPSImage
$photoPoints = Dir E:\dcim –include *.jpg –recurse | Copy-GpsImage -Points $Points ` -verbose -DestPath "C:\users\jamesone\pictures\oxford" ` -Keywords "Oxfordshire" -replace "IMG","OX-" -returnInfo
This is much as it appeared in Part 1 although third command has changed slightly.Copy-GPSImage now has a –returnInfo switch which returns the points where a photo was taken; to link the point to the image file(s) which patched it an extra property Paths is added to the points.
–returnInfo
I mention this because I wanted to show the functions I put added almost for fun at the end. Out-MapPoint and ConvertTo-GPX got brief mentions in part 1: with the data in $photopoints I can push camera symbols through to a map like this : (note the sort –unique to remove duplicate points, 79 is the camera symbol) $photopoints | sort dateTime -Unique | Out-MapPoint -symbol {79}
Out-MapPoint
ConvertTo-GPX
$photopoints
$photopoints | sort dateTime -Unique | Out-MapPoint -symbol {79}
Alternatively I can create a GPX file which can be imported into MapPoint, Google Earth and lots of other tools. GPX files need to be UTF8 text, PowerShell wants to write output files as Unicode – thwarting it isn’t hard but is ugly. $photopoints | sort dateTime -Unique | convertto-gpx | out-file photoPoints.gpx -Encoding utf8
$photopoints | sort dateTime -Unique | convertto-gpx | out-file photoPoints.gpx -Encoding utf8
With the photo points logged it would be nice to show the path I walked but that will have too many points so I wrote Merge-GPSPoint which combines all the points for each minute so I can do Merge-GPSPoints $points | Out-MapPoint or Merge-GPSPoints $points | convertto-gpx | out-file WalkPoints.gpx -Encoding utf8
Merge-GPSPoints $points | Out-MapPoint
Merge-GPSPoints $points | convertto-gpx | out-file WalkPoints.gpx -Encoding utf8
One thing I should point out here is that the GPX format which I convert to is a series of Waypoints (i.e places that will be navigated to in future), not track points (places which have been visited in the past). The import routine processes the latter.
The last detail of the module for now is that I also gave it a function to find out where an image was taken, like this
PS > resolve-imageplace 'C:\users\Jamesone\Pictures\Oxford\OX-43624.JPG' Summertown, Oxford, Oxford, Oxfordshire, England, United Kingdom, Europe, Earth
That’s not a data error when it says Oxford, Oxford. The Geoplaces web service I use returns
Continent
I haven’t done much to introduce intelligence into processing this. I used Trafalagar square in one part 2 and this returns Charing Cross, London, City of Westminster, Greater London, England, United Kingdom, Europe, Earth which is correct but difficult to allow for. To make matters worse all sorts of strange geo-political questions come up as well if you say UK is the country, and England is the topmost Administrative division: English people might well think counties are the tier below parliament adminstratively but since the Scottish parliament and Welsh assembly opened, you might find a different view if you step over the border. Software which works to the American model of displaying the Populated place and First admin Division – for example Seattle, Washington; is easily thrown giving Reading, Berkshire it gives Reading, England. Those are questions to look at another time
In part one of this series I showed the finished version of photo-tagging script I’ve been using. I based my work (which is available for download) on James Brundage’s PSImageTools module for PowerShell which is part of the PowerPack included with the Windows 7 Resource kit (and downloadable independently). In this post I want to show the building blocks that were in the original library provide and the ones I added. Producing a modified image using this module usually means working to the following pattern:
If you are wondering what a filter is, that will become clear in a moment. James B’s original module had these commands.
Get-Image
Add-CropFilter
Add-OverlayFilter
Add-RotateFlipFilter
Add-ScaleFilter
Set-ImageFilter
Get-ImageProperty
ConvertTo-Bitmap
ConvertTo-Jpeg
Copy-ImageIntoOrganizedFolder
You can see there are 4 kinds of filter with their own commands in the list and each one makes some modification to the image: cropping, scaling, rotating, or adding an overlay. Inside the two ConvertTo commands, a 5th kind of filter, conversion, is used and I added a function to create filters to do that. I made some changes to the existing functions to give better flexibility with how they can be called, and added some further functions, mostly to work with EXIF data embedded in the image file. The full list of functions I added is as follows:
Save-Image
New-ImageFilter
New-Overlay
Add-ConversionFilter
Add-ExifFilter
Get-EXIF
Get-EXIFItem
Get-PentaxMakerNoteProperty
Get-PentaxExif
The image below was resized and labelled using these commands. The first step is to create an image to act as an overlay: I’m going to a copyright notice in Red red text, in 32 point Arial
PS> $Overlay = New-overlay -text "© James O'Neill 2008" -size 32 -TypeFace "Arial" ` -color "red" -filename "$Pwd\overLay.jpg"
I’m using a picture I took in 2008: and I could have used a more complex command to build the text from the date taken field in the EXIF data. Next I’m going to create a chain of filters to:
Despite the multi-line formatting here, this is a single PowerShell command: $filter = new-Filter | add | add | add...
$filter = new-Filter | add | add | add...
PS> $filter = new-Imagefilter | Add-ScaleFilter -passThru -height 800 -width 65535 | Add-OverlayFilter -passThru –top 750 –left 0 –image $Overlay | Add-ExifFilter -passThru -ExifID $ExifIDKeywords -typeName "vectorofbyte" -string "Ocean" | Add-ExifFilter -passThru -ExifID $ExifIDTitle -typeName "vectorofbyte" -string "StingRay" | Add-ExifFilter -passThru -ExifID $ExifidCopyright -typeName "String" -value "© James O'Neill 2008" | Add-ConversionFilter -passThru –typeName jpg -quality 70
PS> $filter = new-Imagefilter | Add-ScaleFilter -passThru -height 800 -width 65535 |
Add-OverlayFilter -passThru –top 75
0 –left 0 –
image $Overlay | Add-ExifFilter -passThru -ExifID $ExifIDKeywords -typeName "vectorofbyte" -string "Ocean" | Add-ExifFilter -passThru -ExifID $ExifIDTitle -typeName "vectorofbyte" -string "StingRay" | Add-ExifFilter -passThru -ExifID $ExifidCopyright
-typeName "String" -value "© James O'Neill 2008" | Add-ConversionFilter -passThru –typeName jpg -quality 70
Given a set of filters, a script can get an image, apply the filters to it and save it. Originally these 3 steps needed 3 commands to be piped together like this PS> Get-Image C:\Users\Jamesone\Pictures\IMG_3333.JPG | Set-ImageFilter -filter $filter | Save-image -fileName {$_.FullName -replace ".jpg$","-small.jpg"}
PS> Get-Image C:\Users\Jamesone\Pictures\IMG_3333.JPG | Set-ImageFilter -filter $filter | Save-image -fileName {$_.FullName -replace ".jpg$","-small.jpg"}
I streamlined this first by changing James B’s Set-ImageFilter so that if it is given something other than an image object, it hands it to Get-Image. In other words Get-Image X | Set-Image is reduced to Set-Image X (and I made sure X could be path, including one with wild cards or one or more file objects) . After processing I added a -savepath parameter so that set-image –SavePath P is the same as Set-Image | Save-Image P . P can be a path, or script block which becomes a path, or empty to over-write the image. Get an image, apply the filters to it and save it becomes a singe command. PS> Set-ImageFilter –Image ".\IMG_3333.JPG" -filter $filter ` –SaveName {$_.FullName -replace ".jpg$","-small.jpg"}
Get-Image X | Set-Image
Set-Image X
-savepath
set-image –SavePath P
Set-Image | Save-Image P
PS> Set-ImageFilter –Image ".\IMG_3333.JPG" -filter $filter ` –SaveName {$_.FullName -replace ".jpg$","-small.jpg"}
The workflow for my photos typically begins with copying files from a memory card, replacing the start of the filename - like the “IMG_” in the example above - with text like “DIVE” (I try to keep the sequential numbers the camera stamps on the pictures as a basis for a unique ID). Next, I rotate any which were shot in portrait format so they display correctly and finally I add descriptive information to the EXIF data: keyword tags like “Ocean” and titles like “Stingray”. So it made sense to create a copy-image function which would handle all of that in one command. The only part of this which hasn’t already appeared is rotation. The Orientation EXIF field contains 8 to show the image has been rotated 90 degrees, 6 indicates 270 degrees of rotation, and 1 to show the image is correctly rotated, so it is a question of read the data, and depending on what we find add filters to rotate and reset the orientation data.
copy-image
$orient = Get-ExifItem -image $image -ExifID $ExifIDOrientation if ($orient -eq 8) {Add-RotateFlipFilter -filter $filter -angle 270 Add-exifFilter -filter $filter -ExifID $ExifIDOrientation` -value 1 -typeid $ExifUnsignedInteger }
There is similar code to deal with rotation in the opposite direction, and rotation is just another filter like adding the EXIF data for keywords or title, all job of Copy-Image does is to build a chain of filters to add Title and Keyword tags and rotate the image, determine the full path the new copy should be saved to and invoke Set-ImageFilter. To make it more flexible, gave Copy-Image the ability to add filters to an existing filter chain: in the part one you could see Copy-GPSImage which finds the GPS data to apply to a picture and produces a series of filters from it: these filters are passed on to Copy-Image which does the rest.
Set-ImageFilter.
The last aspect of Copy-Image to look at is renaming: -Replace has become one of my favourite PowerShell operators. It takes a regular expression and a block of text, and replaces all instances of expression found in a string with the text. Regular expressions can be complex but “IMG” is perfectly valid so if I have a lot of pictures to name as “OX-” for “Oxford” I can call the function with a replace parameter of "IMG","OX-" . Inside Copy-Image, the parameter $replace is used with the -replace operator (using PowerShell’s ability to treat “img”,”ox” as one parameter in two parts). $savePath is worked out as follows:
-Replace
“IMG”
replace
"IMG","OX-"
$replace
-replace
$savePath
if ($replace) {$SavePath= join-path -Path $Destination ` -ChildPath ((Split-Path $image.FullName -Leaf) -Replace $replace)} else {$SavePath= join-path -Path $Destination ` -ChildPath (Split-Path $image.FullName -Leaf) }
As mentioned above I went to some trouble to make sure the functions can accept image objects or names of image files or file objects – because at different times, different ones will suit me. So all of the following are valid ways to copy multiple files from my memory card to the current directory ($pwd), renaming, rotating and applying the keyword tag “oxfordshire”
can
$pwd
PS[1]> Copy-Image E:\DCIM\100PENTX\img4422*.jpg -Destination $pwd ` -Rotate -keywords "oxfordshire" -replace "IMG","OX-" PS[2]> dir E:\DCIM\100PENTX\img4422*.jpg | Copy-Image -Destination $pwd ` -Rotate -keywords "oxfordshire" -replace "IMG","OX-" PS[3]> get-image E:\DCIM\100PENTX\img4422*.jpg | Copy-Image -Destination $pwd ` -Rotate -keywords "oxfordshire" -replace "IMG","OX-" PS[4]> $i = get-image E:\DCIM\100PENTX\img4422*.jpg; Copy-Image $i -Destination $pwd ` -Rotate -keywords "oxfordshire" -replace "IMG","OX-" PS[5]> dir E:\DCIM\100PENTX\img4422*.jpg | get-image | Copy-Image -Destination $pwd ` -Rotate -keywords "oxfordshire" -replace "IMG","OX-"
Of course if I have the GPS data from taking the logger with me on a walk I can use Copy-GPSImage to geotag the files as they are copied, and in the next part I’ll look at how the GPS data is processed.
Well… I have been off for a bit and you can have a read of the previous post for some background on that. During that time I’ve done a lot of walking, taking photos as I go. Having raved about my HTC Touch pro 2 and its GPS I’ve been using it to GeoTag those photos. Naturally (for me) PowerShell figures in here somewhere. I’ve added to the image module in the Windows Powerpack that James Brundage wrote. It now takes data from a log and applies it to pictures. It supports several log formats and incidental things I found I wanted to do with GPS data. And it is available for download
I log my walks using Efficasoft’s GPS utilities (on the right). I have a picture of the logger to help with the first of the three PowerShell commands I need to use
Get-CSVGPSData
$points.count
Copy-GpsImage
-verbose
Steps 2 and 3 might be repeated to tag more than one set of photos provided the camera clock is a consistent interval away from “GPS time”. Here’s what a session looks like in PowerShell
PS > set-offset "D:\dcim \100Pentx\IMG43272.JPG" –Verbose Please enter the Date & time in the reference picture, formatted as Either MM/DD/yyyy HH:MM:SS ±Z or dd MMMM yyyy HH:mm:ss ±Z: 04/04/2010 16:02:17 +1 VERBOSE: Loading file D:\dcim \100Pentx\IMG43272.JPG VERBOSE: OffSet = 3607 PS> $points= Get-CSVGPSData 'F:\My Documents\My GPS\Track Log\20100425115503.log' ‑offset $offset PS> $points.count 593 PS> Dir E:\dcim –include *.jpg –recurse | Copy-GpsImage -Points $Points ` -Keywords "Oxfordshire" ` -DestPath "C:\users\jamesone\pictures\oxford" ` -replace "IMG","OX-" ` -verbose VERBOSE: Loading file E:\dcim\100PENTX\IMG43624.JPG VERBOSE: Checking 593 points for one where DateTime is closest to 04/25/2010 12:36:41 VERBOSE: Point 229 matched with variance of 2 seconds VERBOSE: Performing operation "Write image" on Target " C:\users\jamesone\pictures\oxford\OX-43624".
Please enter the Date & time in the reference picture, formatted as Either MM/DD/yyyy HH:MM:SS ±Z or dd MMMM yyyy HH:mm:ss ±Z: 04/04/2010 16:02:17 +1 VERBOSE: Loading file D:\dcim \100Pentx\IMG43272.JPG VERBOSE: OffSet = 3607
PS> $points= Get-CSVGPSData 'F:\My Documents\My GPS\Track Log\20100425115503.log' ‑offset $offset PS> $points.count 593
PS> Dir E:\dcim –include *.jpg –recurse | Copy-GpsImage -Points $Points ` -Keywords "Oxfordshire" ` -DestPath "C:\users\jamesone\pictures\oxford" ` -replace "IMG","OX-" ` -verbose
VERBOSE: Loading file E:\dcim\100PENTX\IMG43624.JPG VERBOSE: Checking 593 points for one where DateTime is closest to 04/25/2010 12:36:41 VERBOSE: Point 229 matched with variance of 2 seconds VERBOSE: Performing operation "Write image" on Target " C:\users\jamesone\pictures\oxford\OX-43624".
In my case this will go through a stack of files, ending VERBOSE: Performing operation "Write image" on Target " C:\users\jamesone\pictures\oxford\OX-43757"
VERBOSE: Performing operation "Write image" on Target " C:\users\jamesone\pictures\oxford\OX-43757"
The picture shows a detail from the Radcliffe Observatory building in Oxford (featured in a recent episode of Lewis) with its GPS co-ordinates visible through File/Properties. I also wrote a little bit of code to push the data from the log though to MapPoint – this ended up as a function Out-MapPoint although I later added a function named convertTo-GPX which does the same job more quickly and also works with programs like GoogleEarth.
convertTo-GPX
$MPApp = New-Object -ComObject "Mappoint.Application" $MPApp.Visible = $true $map = $mpapp.ActiveMap ForEach ($point in $points) { $location=$map.GetLocation($point.Lat, $point.lon) $Pin =$map.AddPushpin( $location, $point.datetime) if ( $point.datetime -lt [datetime]"04/25/2010 12:12:00"){$pin.symbol= 6 } else {$pin.symbol = 7} } The details behind this this take some explaining, so this will be the first of several parts: if you would like to know more have a look at the next few posts where I will drill into how it all works, but if you want to dive in and play the code is available for download now.
$MPApp = New-Object -ComObject "Mappoint.Application" $MPApp.Visible = $true $map = $mpapp.ActiveMap ForEach ($point in $points) { $location=$map.GetLocation($point.Lat, $point.lon) $Pin =$map.AddPushpin( $location, $point.datetime) if ( $point.datetime -lt [datetime]"04/25/2010 12:12:00"){$pin.symbol= 6 } else {$pin.symbol = 7} }
I mentioned in yesterday’s post that I was working on a post about scanned images – in fact it’s the same set of scanned images I was using in this earlier post. In that post I talked about putting Panoramas into SilverLight Deep Zoom
The teams behind Microsoft ICE* – (the Image Composite and Editing tool) and Photosynth have worked together so the newest version of ICE can upload its results into Photosynth: Photosynth is driven by deep zoom so I don’t have to any work to get a shared, zoomable panorama, with Geotagging thrown in. This is not the only great new addition to ICE** it has support for mechanised capture devices which produce an ordered grid or as ICE terms it a structured panorama. You can read more on the HDview blog and on the Photosynth blog (Matt mentions that the ability to see Geotagged panoramas on the same map as Geotagged synths isn’t there yet, but is coming – and I’ve got another post in the pipeline about Geotagging photos) .
I put together a little video to show just how easy the process is (if the embedded video doesn’t work properly, you can view it in its original location) - at 1280x720 resolution it doesn’t really do Photosyth’s viewer justice. You can click the version below and hit the button on the right for the full screen view to see just why I like it so much. I have a couple more panoramas which I will rebuild and upload.
* Should I proud of myself for not making any contrived “ICEmen” jokes ? ** I could have said cool new thing in ICE .
If you believe in the parallel universes then there are ones where Ayrton Senna is celebrating his 50th birthday today, having won 6, 7 or 8 world championships.
In this one, the 50th anniversary of his birth is marked a more sombrely. It’s not quite 16 years since he died with 3 championships to his name and last week when his nephew flipped open the visor on a very similarly patterned helmet to reveal very similar looking eyes I felt like I had seen a ghost – and heard Martin Brundle articulate the same thought on his TV commentary. I said pretty much all I wanted to about Ayrton on fifteenth anniversary of his death. But since I’ve posted recently about scanning pictures and I have another post in draft about that , I thought I’d share a couple of successful scans.
In 1991 Senna looked like he was going successfully defend the title he won in 1990 – he won the first 3 races before Nigel Mansell had got a finish, and he wasn’t even the leading Williams driver until 7th race. The 8th was the British Grand Prix, and I was there. To cap a perfect day for Mansell and a partisan crowd, Senna ran out of fuel on the last lap. Mansell on his victory lap stopped and gave his adversary a lift back to the pits. In this picture you can see how much more exposed the drivers heads were in those days – which was to be the death of Senna in another Williams, 3 years later. Riding back like that is forbidden now, and that too speaks of the attitudes to safety. But it says something to me about the nature of sport that drivers could fight for everything on the track, yet offer help and not be humiliated by accepting it.
The cheap film, second-rate lenses and my own technique limit how good the scan of the photo can be – but I hope the story explains why I treasure it. Far better from a technical point of view is this second picture – but sometimes the technical quality isn’t what matters.
To mark the anniversary, Autosport have a page Ayrton Senna: A life in pictures – they are arranged with the oldest at the bottom – you can see his first F1 test (in a Williams), another shot of the ride home with Mansell in the middle and on the left of the top row is quite a poor shot – you can’t tell what it is from the thumbnail. It’s the back of the car, and I generally don’t keep those. The caption reads “Ayrton Senna, Williams FW16 Renault; 1994 San Marino Grand Prix at Imola.” And then slowly it dawns that the wall and trees in the background mean the car is going into the corner named Tamburello and there’s a big gap to car behind, so this must be the sixth lap – a few seconds after this shot was taken the right front wheel of FW16 hit the wall a little further down than we can see in the shot, and parted company from the car. On another day or in another universe it would have passed harmlessly by, but it didn’t and that picture – like the lift home one – captures what we now know to be a decisive moment.
In another window I am listening to the desktop Virtualization hour which I blogged about yesterday. A couple of hours ahead of the broadcast we posted the press release on Press pass which contained the following detail of what we are announcing today.
• New VDI promotions available for qualified customers to choose from today. Microsoft and Citrix Systems are offering the “Rescue for VMware VDI” promotion, which allows VMware View customers to trade in up to 500 licenses at no additional cost, and the “VDI Kick Start” promotion, which offers new customers a more than 50 percent discount off the estimated retail price. Eligibility and other details on the two promotions can be found at http://www.citrixandmicrosoft.com.
• Improved licensing model for virtual Windows desktop. Beginning July 1, 2010, Windows Client Software Assurance customers will no longer have to buy a separate license to access their Windows operating system in a VDI environment, as virtual desktop access rights now will be a Software Assurance benefit. [Note the new name VDA is what we used to call VECD.]
• New roaming use rights improve flexibility. Beginning July 1, 2010, Windows Client Software Assurance and new Virtual Desktop Access license customers will have the right to access their virtual Windows desktop and their Microsoft Office applications hosted on VDI technology on secondary, non-corporate network devices, such as home PCs and kiosks.
• Windows XP Mode no longer requires hardware virtualization technology. This change simplifies the experience by making virtualization more accessible to many more PCs for small and midsize businesses wanting to migrate to Windows 7 Professional or higher editions, while still running Windows XP-based productivity applications.
• Two new features coming in Windows Server 2008 R2 service pack 1. Microsoft Dynamic Memory will allow customers to adjust memory of a guest virtual machine on demand to maximize server hardware use. Microsoft RemoteFX will enable users of virtual desktops and applications to receive a rich 3-D, multimedia experience while accessing information remotely. [Note the new name RemoteFx is the technology we acquired with the purchase of Calista.]
• New technology agreement with Citrix Systems. The companies will work together to enable the high-definition HDX technology in Citrix XenDesktop to enhance and extend the capabilities of the Microsoft RemoteFX platform.
Good stuff all round, but from a technical viewpoint it’s the new bits in SP1 which will get the attention. I’ll post a little more on what Dynamic memory is and is not in the next day or two.
About a month ago I mentioned that we have a “Desktop Virtualization Hour” planned for 4PM (GMT) tomorrow, March 18th. (That’s 9AM Seattle time, 5PM CET … you can work out the others I’m sure). More information and a downloadable meeting request are Here.
I said then that I thought it might be “more than the average web cast.” and over the last couple of days I’ve had some information about announcements which are planned for the session. Obviously I am not got say what they are until tomorrow, but if you want the news as it breaks – click the link above.
Last week I watched a TV program called Michelin Stars, The Madness of Perfection it talked about the pressure Chefs put themselves under - sometimes tragically so. The presenter was a restaurant critic and in talking to one of his fellow critics they talked about a problem – not exclusively a Michelin one – where every plate was a supreme accomplishment and yet they didn’t want to go to those restaurants.
That’s quite a good analogy for how I look at Ed Wilson’s “PowerShell 2.0 best practices.”. It doesn’t deserve a ranting torrent directed against it, because there are plenty of people who will get a lot from it; but I’m not one of them and it left me frustrated.
My first frustration is the title. A book on best practices should be a slim volume, “Always do this, Try to do that, Avoid so-and-so”. The list of things for PowerShell can’t be enormous, yet this book is big enough to stun an Ox. At over 700 pages it’s the biggest book on PowerShell I’ve met so far. It is padded out with tables and lists which really don’t need to be there - quite early on I came on a 3 page table which lists all the properties of WIN32_processManagement object where it adds no value. A lot of the rest is tips and good ideas – useful stuff, but not helping me to tell good practice from bad. For example two chapters - 65 pages - cover Active directory using ADSI – PowerShell 2.0 introduced cmdlets but these get the briefest of mentions. What I wanted was something to say either – “You’re mad if you don’t ensure you can use the AD cmdlets” or “In these situations you’re better using ADSI because …” .
The second frustration is with the likely reader: if you’re writing for people who know PowerShell and telling them about best practice, I think it’s inevitable they will try to pick holes in the code examples. It would seem that Ed writes scripts to do a task rather than add commands to the PowerShell environment – which is most of what I do – so he and I will have different approaches in places. Although he talks about the importance of making scripts readable, he will produce something with many short lines, where you can’t just understand a section on it’s own. It’s probably easiest to show an example. Given a need to read some data from a file and process it, the book shows something which is structured like this
Param([switch]$verbose)
Function TestPath {...} Function SetConnectionString {...} Function ReadData {...} Function CloseAdoConnection {...} $FilePath = "C:\BestPractices\excel.xls" TestPath($FilePath) SetConnectionString ReadData CloseAdoConnection
The problem with this is you have to start at the bottom with TestPath and then go up to where the function is defined. Then back to bottom to see the next line is SetConnectionString , and then up to where that is defined. Since “up” takes you to a different page / screenful of code, it’s bad for readability. TestPath does a check and exits the script if the file isn’t found – here’s the code:
Function TestPath($FilePath) { If(Test-Path -path $FilePath) { if($verbose) { "$filePath found" } } #end if ELSE { Write-Host -foregroundcolor red "$filePath not found." Exit } #end else } #end TestPath
Notice that a “verbose” response doesn’t go to the verbose channel but becomes output of the function which is a way to introduce some interesting bugs, I would get rid of the function and write
$FilePath = "C:\BestPractices\excel.xls" If ( Test-Path -path $FilePath) { write-verbose "$filepath found" SetConnectionString ReadData CloseAdoConnection } ELSE { Write-Host -foregroundcolor red "$filePath not found."}
Notice there is a CloseAdoConnection but not an open connection ? That’s because SetConnectionString opens the connection: Like the other functions it doesn’t return a result – the connection which it opens is left as a variable for ReadData (which doesn’t just read data in this example but creates AD objects) and CloseAdoConnection to use. Here’s what appears in the book.
Function SetConnectionString() { $strFileName = $FilePath $strSheetName = 'Excel$' $strProvider = "Provider=Microsoft.Jet.OLEDB.4.0" $strDataSource = "Data Source = $strFileName" $strExtend = "Extended Properties=Excel 8.0" $strQuery = "Select * from [$strSheetName]" NewAdoConnection } #end SetConnectionString Function NewAdoConnection() { $Script:objConn = New-Object System.Data.OleDb.OleDbConnection(` "$strProvider;$strDataSource;$strExtend") $sqlCommand = New-Object System.Data.OleDb.OleDbCommand($strQuery) $sqlCommand.Connection = $objConn $Script:objConn.open() $Script:DataReader = $sqlCommand.ExecuteReader() } #end NewAdoConnection
This seems to going out of its way to avoid passing parameters and returning results: but that means you can’t see when SetConnectionString is called that it relies on the $FilePath variable. The functions don’t follow proper naming conventions meaning they can only really be used inside their script (not in a module). Although I’ve seen Ed protest that he is a PowerShell scripter now, but the way the functions are declared with the redundant () after them suggests his VB habits die hard – PowerShell does allow you to declare parameters in brackets, but the convention is to use the Param statement. The VB convention of putting STR in front of strings is followed in some places and not others; but naming isn’t the thing I find horrible with variables and scopes here. SetConnectionString() sets a bunch of variables within its own scope, and then calls NewAdoConnection() – which inherits that scope and relies on those variables. If you decided to move NewAdoConnection() between SetConnectionString and ReadData it would fail. NewAdoConnection() doesn’t return a result but sets a variable for something else in the script to use, but it has to use the script scope to do it. The job could be done in 6 lines rather than 18
$objConn = New-Object System.Data.OleDb.OleDbConnection(` "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + $strFileName +"; Extended Properties=Excel 8.0" ) $sqlCommand = New-Object System.Data.OleDb.OleDbCommand("Select * from [Excel$]") $sqlCommand.Connection = $objConn $objConn.open() $DataReader = $sqlCommand.ExecuteReader()
There is a danger of getting into “PowerShell Golf” – chasing the fewest [key]strokes to reach the target – which can produce something intricate but impossible to understand and maintain. But here I think the shorter version is clearer and easier. There’s a case to be made for keeping New-AdoDataReader as a function, but it should be reusable, and this isn’t. It should take the parts of the connection string as parameters and return a result, and this doesn’t
I don’t like the habit of never writing a constant, but always assigning it to a variable first and then using the variable (it’s even worse here with $filePath being put in a new variable $strFileName ) and again you can write code which uses no variables but at the price of making it incomprehensible. In this case if you looking through the ReadData function trying to work out what it does, you have where find where another variable was set, and to find out how it was set you have to find where other variables are set.
This “variablitis” copes up in many places , and Ed has written that the constraints of the 75 character page width in a book can cause this, but I spotted this example
$os = [environment]::osversion $os | Get-Member -MemberType property
Writing it properly would only take 60 characters.
[environment]::osversion | Get-Member -MemberType property
Once I started seeing these things I kept tripping over them. For example, Powershell supports for loops in the style of C like this .
For($i = 0 ;$i -le 10; $i++) {doSomethingWith $i}
But people who work in PowerShell would more commonly write
1..10 | ForEach {doSomethingWith $_}
Again one can argue this “PowerShell golf”, but is it easier to read “1..10” or “Set i to 0, while I is less than 10, increment i” . I choked when I saw it here.
Function Get-MoreHelp { # .help Get-MoreHelp Get-Command Get-Process For($i = 0 ;$i -le $args.count ; $i++) { Get-Help $args[$i] -full | more } #end for } #end Get-MoreHelp
There isn’t really any justification for writing
For($i = 0 ;$i -le $args.count ; $i++) { doSomethingWith $Array[$i]}
Instead of
$Array | foreach { doSomethingWith $_ }
But the bigger issue for me using args instead of named parameters is generally discouraged and doing so to get the user passes a list of items as separate un-named parameters rather than doing what all PowerShell’s built in cmdlets do and writing a comma separated list, well it’s just wrong.
Ultimately this was what stopped me getting value from the book – there were so many departures from accepted good practice that I lost faith in it as a book on best practice. If MS Press or Ed himself had used a title like “Improve your PowerShell” I would have had a lot less of a problem with it. There is good content, and lots of contributions from people with proven expertise. But you can’t blindly order copies for a team who work with PowerShell and tell them to use it as a Style guide. On the other hand if you’re in a bookshop and see it on the shelf I’d recommend having a thumb through it (I look up something I’ve been trying to do and see what the explanation is like) – it might suit you better than it suited me.
Windows PowerShell 2.0 Best Practices By Ed Wilson is published by Microsoft press ISBN 978-0-7356-2646-1 List price £47.49
Every now and then a news story comes up which reminds us that if people with bad intentions, even sensible people can fall into traps on-line. There was one such story last week where friends of the victim said she was “the sensible one” – if she wasn’t unusually gullible it could happen to anyone. I wrote about safer internet day recently and it’s worth making another call to readers who are tech savvy to explain to others who are less so just how careful we need to be trusting people on-line. I got a well constructed phishing mail last week claiming to have come from Amazon I would have fallen for if it had been sent to my home rather than work account – it’s as well to be reminded sometimes we’re not as smart as we like to think.
I’ve also been reading about a libel case. I avoid making legal commentary and won’t risk repeating a libel: the contested statement said that something had been advocated for which there was no evidence. I read a commentary which said something to the effect that in scientific disciplines, if your advocacy is not in dispute and someone says you have no evidence for it, you produce the evidence. Without evidence you have a belief, not a scientific fact. This idea came up on later in the week when I was talking to someone about VMware: you might have noticed there is a lack of virtualization Benchmarks out in the world, and the reason is in VMware’s licence agreement (under 3.3)
You may use the Software to conduct internal performance testing and benchmarking studies, the results of which you (and not unauthorized third parties) may publish or publicly disseminate; provided that VMware has reviewed and approved of the methodology, assumptions and other parameters of the study
Testing, when done scientifically, involves publishing ,methodology, assumptions and other parameters along with the test outcomes and the conclusions drawn That way others can review the work to see if is rigorous and reproducible. If someone else’s conclusions go against what you believe to be the case, you look to see if they are justified from the outcomes: then you move to the assumptions and parameters of the test and it’s methodology. You might even repeat the test to see if the outcomes are reproducible. If a test shows your product and yours is shown in a bad light then you might bring something else to the debate. “Sure the competing product is slightly better at that measure, but ours is better at this measure”. What is one to think of a company which uses legal terms to stop people conducting their own tests and putting the results in public domain for others to review ?
After that conversation I saw a link to an article IE 8 Leads in Malware Protection . NSS labs have come out with their third test of web browser protection against socially engineered malware*. The first one appeared in March of last year, and it looks set to be a regular twice yearly thing. The first one pointed out that there was a big improvement between IE7 and IE8 (IE6 has no protection at all if you are still working for one of the organizations that has it, I’d question what you’re doing there). IE 8 does much better than its rivals : the top 4 have all improved since the last run of of the tests. IE was up from 81 to 85% , Firefox from 27 to 29%, Safari from 21% to 29% and Chrome from 7% to 17%:
Being pessimistically inclined I look at the numbers the other way round : in the previous test we were letting 19 out of every 100 through, now it’s 15 – down by 21%: in the first test we were letting 31 of every 100 through so 52% of what got through a year ago gets blocked today. Letting that many through means we can’t sit back and say the battle is won, but IE8 is the only Browser which is winning against the criminals: Google,for example, have improved Chrome since last time,so it only lets through 83 out of every 100 malware URLs - that’s blocking 11% of the 93 it let through before from each 100. With every other browser the crooks are winning, which is nothing to gloat over - I hope to see a day when we’re all scoring well into the 90s.
I haven’t mentioned Opera – which has been have been consistently last, and by some margin, slipping from 5% in the first test to 1% in the second to less than 1 in the most recent. In a spirit of full scientific disclosure I’ll say I think the famous description of Real Networks fits Opera. Unable to succeed against Safari or Chrome , and blown into the weeds by Firefox, Opera said its emaciated market-share was because IE was supplied by default with Windows. Instead of producing a browser people might want, Opera followed the path trodden by Real Networks – complaining to the European Commissioner for the protection of lame ducks competition. The result was the browser election screen.
I’m not a fan of browser election screen – not least because it is easily mistaken for Malware. To see the fault let me ask you, as reader of an IT blog, which of the following would you choose ?
You might say (for example) “I want Firefox”, but which is Firefox in that list ? You are probably more IT savvy than the people the election screen is aimed at and if you can’t choose from that information, how are they supposed to ? You see, if you have done your testing and know a particular browser will meet your needs best, you’d go to it by name you don’t need the screen. People who don’t know the pros and cons of the options before seeing the screen might just as well pick at random - which favours whoever has least market share – which would be Opera.
The IE 8 Leads in Malware Protection article linked to a post of Opera’s complaining that the results of the first test were fixed “Microsoft sponsored the report, so it must be fixed!” If we’d got NSS labs to fix the results a year ago would we stipulate that Opera should be so far behind everyone else? Did we have a strategy to show Opera going from “dire failure” to “not even trying”? Or that IE8 should start at a satisfactory score and improve over several surveys with the others static ? But to return to my original point: the only evidence which I’m aware of shows every other browser lets at least 4 times as much Malware through as IE. The only response to anyone who disputes it is let’s see your evidence to counter what NSS labs found.Google have spent a fortune advertising Chrome: if Chrome really did let fewer than 5 out of 6 malware sites through they’d get someone else to do a [reviewable] study which showed that.
And since we’re back at the question of evidence, if you want are asked for advice on the election screen and you want to advocate the one which will help people to stay safe from Phising attacks – I don’t think you have any evidence to recommend anything other than IE. But remember it’s not a problem which can be solved by technology alone. Always question the motives of something which wants to change the configuration of your computer.
You may have seen that registration for UK TechDays events from 12th to 16th April is already open - but you probably won’t have seen this newly announced session, even if you are following @uktechdays on twitter
After Hours @ UK Tech Days 2010 – Wednesday 14th April, 7pm – 9pm. Vue Cinema, Fulham Broadway.
Reviving the critically acclaimed series of mad cap hobbyist technology demonstrations – After Hours reappears at Tech Days 2010. After Hours is all about the fun stuff people are building at home with Microsoft technology, ranging from the useful ‘must haves’ no modern home should be without, too the bleeding edge of science fiction made real! Featuring in this fun filled two hour installment of entertaining projects are: Home Entertainment systems, XNA Augmented Reality, Natural User Interfaces, Robotics and virtual adventures in the real world with a home brew holodeck!
Session 1: Home entertainment.
In this session we demonstrate the integration of e-home technologies to produce the ultimate in media entertainment systems and cyber home services. We show you how to inspire your children to follow the ‘way of the coder’ by tapping into their Xbox 360 gaming time.
Session 2: Augmented reality.
2010 promises to be the year of the Natural User Interface. In this session we demonstrate and discuss the innovations under development at Microsoft, and take an adventure in the ultimate of geek fantasies – the XNA Holodeck.
Like all other techdays session this one is FREE to attend - if you hadn’t heard: UK Tech Days 2010 is a week-long series of events run by Microsoft and technical communities to celebrate and inspire developers, IT professionals and IT Managers to get more from Microsoft technology. Our day events in London will cover the latest technology releases including Microsoft Visual Studio 2010, Microsoft Office 2010, Virtualisation, Silverlight, Microsoft Windows 7 and Microsoft SQL Server 2008 R2 plus events focusing on deployment and an IT Manager day. Oh and did I say they were FREE
Monday, 12 April 2010 - Virtualization Summit – From the Desktop to the Datacentre
Designed to provide you with an understanding of the key products & technologies enabling seamless physical and virtual management, interoperable tools, and cost-savings & value.
Tuesday, 13 April 2010 - Office 2010 - Experience the Next Wave in Business Productivity
The event will cover how the improvements to Office, SharePoint, Exchange, Project and Visio will provide a practical platform that will allow IT professionals to not only solve problems and deliver business value, but also demonstrate this value to IT’s stakeholders.
Wednesday, 14 April 2010 - Windows 7 and Windows Server 2008 R2 – Deployment made easy
This event will provide you with an understanding of these tools including the new Microsoft Deployment Toolkit 2010, Windows Deployment services and the Application Compatibility Toolkit. Understanding of these tools including the new Microsoft Deployment Toolkit 2010, Windows Deployment Services. We will also take you through the considerations for deploying Windows Server 2008 R2 and migrating your server roles.
Thursday, 15 April 2010 - SQL Server 2008 R2 – The Information Platform Highlighting the new capabilities of the platform, as well as diving into specific topics, such as consolidating SQL Server databases, and tips and techniques for Performance Monitoring and Tuning as well as looking at our newly released Cloud platform SQL Azure.
Friday, 16 April 2010 (IT Managers) - Looking ahead, keeping the boss happy and raising the profile of IT IT Managers have more and more responsibilities to drive and support the direction of the business. We’ll explore the various trends and technologies that can bring IT to the top table, from score-carding to data governance and cloud computing.
Monday, 12 April 2010 (For Heads of Development and Software Architects) Microsoft Visual Studio 2010 Launch - A Path to Big Ideas
This launch event is aimed at development managers, heads of development and software architects who want to hear how Visual Studio 2010 can help build better applications whilst taking advantage of great integration with other key technologies. NB – Day 2 will cover the technical in-depth sessions aimed at developers
Tuesday, 13 April 2010 Getting started with Microsoft .NET Framework 4 and Microsoft Visual Studio 2010 WAITLIST ONLY Microsoft and industry experts will share their perspectives on the top new and useful features with core programming languages and in the framework and tooling, such as -- ASP.NET MVC, Parallel Programming, Entity Framework 4, and the offerings around rich client and web development experiences.
Wednesday, 14 April 2010 The Essential MIX Join us for the Essential MIX as we continue exploring the art and science of creating great user experiences. Learn about the next generation ASP.NET & Silverlight platforms that make it a rich and reach world.
Thursday, 15 April 2010 Best of Breed Client Applications on Microsoft Windows 7 Windows 7 adoption is happening at a startling pace. In this demo-driven day, we’ll look at the developer landscape around Windows 7 to get you up to speed on the operating system that’ll your applications will run on through the new decade.
Friday, 16 April 2010 – Registration opening soon! Windows phone Day Join us for a practical day of detailed Windows Phone development sessions covering the new Windows Phone specification, application standards and services
There will also be some “fringe” events , these won’t all be in London and I’ll post about them separately (James in the Midlands, I’ve heard you :-) )
As titles go that’s an odd one, but stay with me.
I’ve written before about my Citroen C6: Before Christmas a warning message popped up saying something was wrong with the hydro-pneumatic suspension which give the big Citroens their wonderful ride. A visit to the garage confirmed the problem was real – not a diagnostic issue, and lay with a part which rarely goes wrong i.e. one no dealer keeps in stock. It would be take a day or two to get the part and by the time it was fitted I needed to be at Tech-ed in Berlin. I expected the car to be ready when I got back, but it wasn’t. Having replaced the faulty part it turned out it had failed because of a fault in the hydraulic pump: this is beyond rare – Citroen UK told me later that they’d only ever supplied one before and that was after an accident, but I’m getting ahead of myself. The pump should have arrived before I got back from Tech-ed, but there was no sign of it. We then began a sequence where every few days I would call the garage or they would call me, and I’d get the news the pump had not arrived but would be there in a couple of days.
I’m not totally without patience, but after 3 weeks I was getting cross and started to tweet about it, and found Citroen UK on Twitter. So I posted things like Day 26 of my Citroen C6 being in the Garage. @Citroenuk promised to deliver the part today and they #Fail to. Now promising Thursday. It was partly to vent and partly to see if Citroen responded - if your organization is “doing social media” you really should know what you’re going to do if someone complains – we try to do this at Microsoft when it isn’t the “I hate Microsoft because they’re a big money making concern” variety. Citroen UK’s twitter account turned out to be someone from marketing who took enough ownership of the problem to get some information and make sure the right person saw it. That was how I ended up talking to Brian (I’ll keep his last name out of it – I can see just people calling Citroen asking for him). If Brian was trained in customer care (rather than doing it by instinct) his teacher would have been pleased: he apologized (sincerely - not in an over the top way), saw the customer’s point of view “I know Caterpillar have a ‘parts anywhere in the world in 24 hours, or Cat pays’ promise. You should be able to get a part here in 24 days for your top of the range model”, explained why it had gone wrong (the pumps showed as in stock but been taken to be modified to the latest specification), committed to speeding the resolution of the problem and promised to follow-up to talk about how Citroen could rebuild the relationship. I’ve had Citroens (7 of them) for 16 of the last 20 years, so I guess I qualify as a loyal customer they’d want to keep.
Brian had an unexpected spell off work so it was well into January by the time he got in touch, and offered me a choice of accessories as compensation. I wanted to be able to plug in a music player in the car – I’ve tried those little FM transmitters and found on a decent length journey they’re more trouble than they’re worth. The accessory catalogue had a “USB box” which plays MP3s. Some of the other options which Brian was willing to pay for were pretty pricey and would have felt like taking advantage, but this seemed OK. It took a while to get the kit and sort out a day to fit it, but it went in last week and I have to say it’s a pretty neat gadget. The handbook suggests it goes in lot of cars - Peugeot and Citroen across the PSA group; it has a USB socket which is powered, so will charge my phone (I’ve twice blown the cigar lighter socket fuse with cheap adapters), plus a dedicated iPod socket – which will work with my wife’s nano, and a 3½mm jack plug for anything else. I tried playing a few MP3s I’d copied to a memory stick – and the first impression was nice sound quality: the integration with the built in Stereo isn’t perfect but is quite good enough. But there was better news: it turns out the USB box plays pretty much any format, including WMA, WAV and even OGG format. Most of my music is in WMA format and sync’d to my phone, so just I tell the phone to connect in storage mode by default , plug it in (even if locked) and the USB box reads the files and plays them.
Playing OGG isn’t quite the advantage it might be when Co-pilot is installed on the memory card, because it uses OGG files for all its messages, and the USB box thinks it should play them – so the first thing it played was “Take 1st exit at roundabout” , “Take 2nd exit at roundabout” and so on. I set the files to hidden, interestingly file explorer on the phone ignores the hidden attribute, so I can’t blame the USB box for doing the same. It’s not an insurmountable problem, unlike its predecessors this phone has enough main memory to allow me to move Co-pilot’s sound files off the storage card. So that’s another plus for the phone.
And as far as the car is concerned it’s one more thing to like about driving it, I’ve had another, minor problem since which was quickly fixed and thanks to Brian I’m back in the happy customers column.