# Tuesday, May 20, 2008
Today at REMiX '08 Sydney (Also see VisitMIX) along with a good show and a grand feed, attendees also got a copy of Expression Studio 2.  After seeing it in action I'm quite looking forward to taking it around the block.  I never quite got into [Macromedia|Adobe]Flash, and am quietly hoping Silverlight can find a spot next to it in the web ecosystem.

First thing I did when I got home was install Expression Studio, I got a little curious to find that there is a Visual Studio 2008 Standard disk in the box.  It got me to wonder what really is the difference between VS Pro which I am using at the moment and VS Standard?

I can't remember the product comparison pages for any version of Visual Studio on MSDN ever being completely illuminating.  The 2008 version is about as good as it gets it seems

The one that I am most interested in somehow is down the end of the list:  the inclusion of the Unit Testing features in VSPro 2008, when it was only included in Team System versions of VS 2005.  Here is a slightly abridged summary of the other features included in VS Professional that you do not get in VS Standard:

Debugging Tools:
  • Attach to Remote Process
  • SQL-CLR Debugging
  • XSLT Debugger
  • T-SQL Debugging
Data Tools:
  • Database Projects
  • SQL Server Projects
  • Server Explorer
Reporting:
  • Crystal Reports Application & Crystal Reports for Visual Studio
Office development:
  • VSTO for Office 2003 and Office 2007
  • Sharepoint 2007 State Machine workflow template
Smart Device Development:
  • Device Emulator
  • Project Templates
  • Debugging Tools


...but surely this can't be it?

It's not.  Well, this is the story if you are comparing VS Pro and VS Standard alone, but there is one other thing to consider:
  1. In my timezone, the full boxed retail VS Standard is less than half the price of the equiv. VS Professional... but;
  2. You can't get an MSDN Subscription including VS Standard.  They are only available with Professional and above, and imho the licensing benefits of MSDN for developers is well worth the look.
So there you have it.  If an MSDN Subscription is on your radar, enjoy using VS Pro.  If it is not, and you can live without the above listed features, well maybe there is no need to spend more than you have to.

Tuesday, May 20, 2008 10:56:04 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, April 01, 2008
This is the first in what I hope will become a series on the new language features in C# 3.0 used in .NET 3.5 / Visual Studio 2008.

One thing I am not intending to cover is LINQ.  Just because the blogosphere has been buzzing with LINQ articles since the early days of "Orcas".  And with good reason I hasten to add!

Where I am starting is with the var keyword.

VB6 veterans will remember the Variant type.  A Variant could contain anything, even Object.  While this was sort of useful, my memory of it is as a synonym for:  I can't be bothered, lets just stick it in a Variant and deal with it later.

There was also a performance impact of using the special Variant type, they were large in memory and have an overhead of extra runtime checking that added up; like when assigned inside a loop for example.  They were also a special case in their un-assigned form, taking on the value Empty (test with IsEmpty()) vs Nothing (test with Is Nothing). 

So when I saw var added to C# I raised my eyebrows in the way a Fed might, when the beagle sits quietly next to your suitcase at the airport.

Most of the time you see it in the samples, it is used when returning an Anonymous Type from a LINQ query.  And this is the clue!  var is not itself a type, but instead it is a signal to the compiler to infer the type of an operation, and substitute in the required type.  It does not even have to be an Anonymous Type.  Consider the following simple example:

var result = 10 / 2.0;
Console.WriteLine(result.ToString());

By the time this code is compiled, var is replaced with double.  In fact, the Intellisense on result will be correct for it being a double.

To confirm this, looking at those lines of the assembly in Lutz Roder's Reflector show the following after disassembly:

double result = 5.0;
Console.WriteLine(result.ToString());


OK, so var can be used independant of Anonymous Types, but why would you want to be less explicit in typing your variables?  Consider the following fictitious example:

DatabaseRequestService req = DatabaseRequestService.CreateFrom(value);

And compare it with the equivalent line using var:

var req = DatabaseRequestService.CreateFrom(value);

Here, var leads itself to much more readable syntax with the same typing, Intellisense, and everything else!

Listening To:  Róisín Murphy

Tuesday, April 01, 2008 9:25:00 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, March 05, 2008

One of the things I miss from my Unix/Linux days is Grep.  Previously I have tried things like Cygwin, but was never quite satisfied.  I am quite excited about PowerShell and am always trying to get more PS> in my life :-)

I'm using Powershell almost daily to replace Grep.

To start, this is all based on the Get-ChildItem cmdlet.  The best way to think about Get-ChildItem is it does what the Dir command did in DOS.  One important difference is it is not just for files, and can be used to return all items in a location - and it is up to each provider to decide what a location & item means to it!

For the PowerShell n00bie, you can just use cd around the filesystem and when you type dir, you are really running Get-ChildItem.  In fact when you type cd you are really running Set-Location.  For a full list of aliases for common commands, run Get-Alias.

To search in file names:

The following command searches for .aspx & .ascx files in the current directory that have the word "metro" in the filename.

PS > Get-ChildItem -Include *metro*.as?x

To search inside text files:

The following command searches inside .aspx & .ascx files in every subdirectory that have the word "metro" in the filename, and has the word "train" inside the file.

PS > Get-ChildItem -Recurse -Include *metro*.as?x | Select-String -Pattern train

You are also able to add the -CaseSensitive parameter to the end of the Select-String command, by default it will search case insensitive.

NB:  I have used the full names of the parameters of the commands.  This may look clunky, but:

  1. I wanted the examples to be clear, because this is a blog :-)
  2. The Tab-Completion feature works for parameter names so they are not hard to type
  3. You can use the smallest number of letters that identify a parameter.  For example, if a cmdlet accepts a -Recurse and a -Record param, you would only need to use -Recu and -Reco respectively.

Update: A lot of parameters accept an array as input.  The syntax for listing these is as a comma seperated list.

An example where this applies to our example is searching through multiple file types, i.e. .aspx and .cs.

The following example searches both .aspx/.ascx files and .cs files with the word "metro" in the filename.

PS > Get-ChildItem -Recurse -Include *metro*.as?x,*metro*.cs

Listening To:  Wicket Beat Sound System, Inner Styles

Wednesday, March 05, 2008 11:25:19 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, February 15, 2008

Out of the blue I got this message from iTunes today:

iTunes has detected an iPod in recovery mode.  You must restore this iPod before it can be used with iTunes.

Fair enough, foo happens, life goes on.  Or so I thought.  When you restore your iPod and reboot it, the same message comes back!  Over and over.

The solution, it turns out according to the collective wisdom of the blogs, is to change the drive letter of your iPod in Computer Manager.

Mine had, for reasons not yet understood, changed from J: to H: - which was in use as a network-mapped home drive.  This conflict was being reported in iTunes as an iPod in Recovery Mode.

It seems like all I do these days is download iTunes updates, and the messages are not getting any better when it goes belly-up.

Apple, this is turning into a one way relationship!

Listening To:  Zephyr Timbre, Absrtakt Fusion

Friday, February 15, 2008 1:57:52 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [2]  | 
# Thursday, February 07, 2008

Sydney had some very heavy storms today, on the back of what is an unseasonal string of storms.  The drains outside my new home office were at capacity for the first time and with the rain coming down…

It flooded

However by and large things went well.  First thing was to cut mains power to the room as a puddle was forming under my rack.  A laptop was on hand and the LAN infrastructure was on power protection, so all the machines that matter shut down cleanly. 

What did I learn?

  • My SQL Server (Proliant ML530, 2x Xeons, 3Gb, Ultra3 RAID) takes the longest to shut down so should be shut down first.  Tacitly I knew this, but didn’t connect the dots at the time (with the UPS ticking away)
  • Power packs, in fact mains power in general should be off the floor.  I am gonna make a policy about this.  Again it could have been a lot worse but it was a distraction with the clock ticking.  Command hooks are cheap and I will be making some CapEx 3M’s way shortly.
  • The floor is a bad place to stack paperwork.  Nothing important was lost but Rob and Coronel has a date with the hair dryer
  • One of my UPSes goes Red with plenty of juice to spare.  Might need to do more testing.

 

Thursday, February 07, 2008 6:46:14 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, January 23, 2008

Lots of people are familiar with obtaining and installing SSL Certificates for hosting secure web sites, but the area of code signing seems less cohesive. I’ve compiled some notes I have on the process together in this blog post.

Yes, but who are you?

Reputable publishers of code signing certificates require some evidence that you are authorized with respect to the organization you wish to have named on your certificate. In my case, being able to produce the ASIC registration for my company was enough, YMMV.

This is subtle, but important.

  1. My company rego papers are credentials a Root CA (e.g Comodo, Verisign, Thawte, USERTrust etc) uses to trusts me.
  2. The user (implicitly) trust the Root CA by using an OS with their Certificate installed.
  3. Ergo, the user (indirectly) trusts me.

Macro projects in Microsoft Excel/Word/Visio/Access/etc

Once you have obtained your certificate, you are able to sign Macro projects in Office document templates by choosing Tools -> Digital Signature.

Your newly purchased certificate will appear in the list and by saving the project your template is signed. The difference is now the user is asked to trust you (as verified by the CA) and your code, rather than being asked to enable all macros.

Software distributed MSI packages

Signing MSI packages and CAB files is more visible than ever before in Windows Vista. This I think is a good thing, however I do worry that because there are a lot of unsigned installers out there that users may get the message that it’s not that important.

Once you have got your certificate from a CA, the process couldn’t be easier. There are a couple of ways to get signtool.exe, I usually have the Windows SDK on my machines which ships with it.  The command to sign ClassLibrary1.dll for example is: (assuming signing from a pfx, not the local cert store)

C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\signtool.exe sign /f My_Code_Signing_Cert.pfx /p L0ng5ecr3tp@ssw0rd /d name /du http://www.MyCompany.com /t http://timestamp.verisign.com/scripts/timestamp.dll ClassLibrary1.dll

The time stamping is important here, in that certificates expire. An external time stamp ensures that the assembly was signed while the certificate was valid.

.NET Assemblies

Technically, signing an assembly is not unlike signing an MSI. On one hand it is easier because you can do the signing from inside Visual Studio’s project properties

On the hand there is the concept of delay signing, where the actual private key is not available to the developer on a day-to-day basis.  This added security adds a layer of complexity that is frankly beyond the scope of this post. I will come back and dedicate a whole post to it some time :-)

Windows Logo Certification / WinQual

This is the only case I can think of where the vendor of the certificate matters. A certificate from VeriSign is required to prove your identity in the WinQual program, which is required for a Windows Logo certification. VeriSign has special pricing is on offer for members of Windows Quality Online Services site.  The $99 cert from VeriSign is required for WinQual membership, and is all you need if you already have a code signing certificate. The $399 cert is valid for both code signing and WinQual membership.

Wednesday, January 23, 2008 4:26:10 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, January 14, 2008
So looking forward to another year in Visual Studio, and this year in Visual Studio 2008 no less! 

I thought I'd open 2008's blog posts with a note about what is in my toolkit at the moment for developing in VS2008.  So in no particular order...

What is in?

  • Visual Studio 2008.  I played with it since Beta1, and blogged about it a bit too.  Living in the RTM now and quite liking it.
  • Refactor! Pro and Coderush from Developer Express are still on my list.  There is a new version (3.0.5 at time of writing) out that has some cool new improvements.
  • Aptana Studio.  I heard about this Eclipse-based IDE on the Hanselminutes podcast and had to check it out.  There are some good features in there for CSS and JS.  Worth having around and they cram a lot of IDE into a tiny space!
  • The PowerShell Visual Studio Templates.  Powershell is getting more and more use in my life, and I love the idea of rolling your own cmdlet (pronounced:  "command-let") to manage your own apps.  The page says they are for VS2005 but they are good for VS2008 as well.
  • NMock.  I know there are plenty of mocking frameworks out there each with their own style.  I just happen to like NMock.


What is out?

  • The notable exclusion from my 2008 dev environment is NUnit.  I have been a fan and user of NUnit for some time, but am going with the MSTest-based unit testing framework that is built in to Visual Studio 2008.
  • NAnt is on thin ice in my environment too in favour of MSBuild.  This is largely for pragmatic reasons, there is project information kept in both the VS Solution and in the NAnt file and my preference is to maintain it in one spot only.

And that's it!  I like to keep it light.  For Continuous Integration I am using CruseControl.NET.

I'm still searching for the perfect XPath/XSLT environment.  Visual Studio is OK for the moment, but I have a feeling that the perfect tool may just be Eclipse based :)
Monday, January 14, 2008 11:45:38 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, December 12, 2007
One question I have strugled to answer clearly in past is What is the difference between Windows Sharepoint Services (WSS 3.0) and Microsoft Office Sharepoint Server?

The first difference is in the name, and is best highlighted in the words of Richard Campbel of DNR/Run-As fame:  When it is a service it is free, when it is server you have to pay for it.

The following diagram shows how I keep them apart in my mind:




To explain a bit: this is not a complete list of features, and not the most important features, just my favs :-)

So if you have any features that you think are really important and didn't get a mention, leave me a comment!

Listening To: You're Living All Over Me, Dinosaur Jr.
Wednesday, December 12, 2007 5:03:40 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, November 27, 2007

The problem with IIS6 that I have been curious about but up until today never needed a solution for.

The problem I am talking about is that with the IIS 6.0 UI you cannot set a host header on a SSL port for a domain.  You can live a long and happy life with a 1-cert-per-server config but with the case of a wildcard cert (one covering all subdomains of the domain it was purchased for) you really want to be able to take advantage of these extra subdomains.

Consider an example from a server below.  The two sites that are highlighted belong to the same domain - Lets call the red one www.MySite.com and the blue one shop.MySite.com.  There is a wildcard cert installed on the machine for *.MySite.com.

The first one is easy.  Install the cert and assign it to the site.

Setting this on subsequent sites on the same box is where you get the problem.  It can be done, and it isn't hard, you just have to know the trick!

The trick is the adsutil.vbs script that is included when you install IIS.  The default path to find these scripts is: C:\Inetpub\AdminScripts.

The process for assigning a host header for SSL to all subsequent sitess is:

  1. Don't assign a SSL port number to the second site.  Leave it on port 80 for now
  2. Open a command window and change to the path with adsutil.vbs.
  3. Run the following command:  cscript.exe adsutil.vbs set /w3svc/<site identifier>/SecureBindings ":443:<host header>"   In our example above the <site identifier> is replaced with the Id of the blue site, 1023406912, and the <host header> is replaced with shop.MySite.com
  4. adsutil will assign port 443 to the site, you do not need to reset IIS

TechNet has a rundown of all the things you can do with adsutil.vbs and IIS6, so check it out.  But don't get too attached - the Metabase is not showing up for IIS 7!

Listening To: The Boatman's Call, Nick Cave and the Bad Seeds

Tuesday, November 27, 2007 7:32:41 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [1]  | 
# Tuesday, November 20, 2007

I just saw these and thought they were worthy of linkage

Clinic 2806: Microsoft® Security Guidance Training for Developers.

Clinic 2807: Microsoft® Security Guidance Training for Developers II.

There is a good breadth of topics covered, and the price is right :-)

Tuesday, November 20, 2007 11:37:00 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, November 19, 2007

OK I'm wheeling out the Sharepoint Annoyances category for one last random show - until next time (kinda like the Rolling Stones)

The problem comes when you remove WSS 3.0 from a box and the instance of Microsoft SQL Server 2005 Embedded Edition (SSEE) does not get removed. 

This is by design, however if the reason you are removing WSS 3.0 is because of a problem with the SSEE database you have a problem.

It turns out it is easy to uninstall after all - I found the answer via Jérémie Clabaut's blog.

The good news is it is a one liner to call msiexec.  Quoting Jérémie:

msiexec /x {CEB5780F-1A70-44A9-850F-DE6C4F6AA8FB} callerid=ocsetup.exe

As is documented elsewhere - don't forget to move away / delete any errant Mdf/Ldf files as they can interfere with the reinstall. 

Thanks Jérémie!

Listening To:  The Velvet Underground and Nico, The Velvet Underground

Monday, November 19, 2007 9:13:12 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [1]  | 
# Wednesday, November 14, 2007

So I recently got my first Bluetooth phone.  The whole purpose of the phone was to keep my calendar on the road in sync with my shiny new notebook, and it worked out OK actually.

Being a nerd I was curious about the Bluetooth protocol and how it works, the following is an architectural overview of how the protocol is used to sync calendar and todo items:

Outlook: oh Hai, iz me
Phone: Hai
Outlook: haz new itemz?
Phone: ya
Outlook: o rly?
Phone: ya rly, Lulz
Outlook: Can has new itemz?
Phone: here iz itemz rite now, k
Outlook: I has new itemz2
Phone: Srsly?
Outlook: ya, here iz them
Phone: we kool? awsum. kthxbai

Wednesday, November 14, 2007 11:12:24 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, November 06, 2007

I got this message again this morning and I am so sick of it!

Only 16 chars?  O RLY?  What if my dog's name is more than 16 chars long?

Further investigation of the JS source reveals that other error messages include:

Password can only contain letters and numbers

I am always talking to people about password policy and no wonder people are confused.  So much good guidance out there is buried under so much rubbish.

Compare this to the other user experience that is becoming more common:

Much better!  There was a time when it would be appropriate to explain why the second case is better... but in this day and age it should be obvious.  It is all about coercing people to do good passwords until they are made obsolete in the future.

Since Version 1.0.60731.0 of the ASP.NET AJAX Control Toolkit there has been a quite good Password Strength control available to the ASP.NET platform.  Everyone else (like my first, deliberately anonymous example) can just Google it!  There are plenty of samples available.

One that I liked was at Gerd Riesselmann's blog, where he shares (GPL) a simple example suitable for learning how this is done.

What do you think?  Is there any excuse for giving poor password guidance in 2007?

Tuesday, November 06, 2007 10:37:32 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, October 30, 2007

(I know, every year!  and you will see it next year too so long as I am able to type :) )

Because 31 oct == 25 dec

Listening to: You am I, Hourly Daily

Tuesday, October 30, 2007 9:05:29 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, October 24, 2007

So today I took delivery of my shiny new XPS M1330, here is my thoughts so far [end of day 1]

Background:

For years (and years…) I have been using a Dell Inspiron 1100.  I think of it as the little laptop that could.  I had a P4 and 1Gb of RAM but it didn’t take much to bring it to a halt.  It also generated enough heat that I had global warming protesters picketed outside for a month… I tried Vista on it and it had a WEI of 1, and to top it off I cannot live in 1024x768 for one more day!

So trying to run the latest hotness like Visual Studio 2008 and SQL Server 2008 betas was completely out of the question.

It would also blue screen switching between screen and VGA out.  OK, enough space spent on the old, bring on the new!

The new hotness

So I bit the bullet and went in for a new laptop.  After much research I chose the Dell XPS M1330.  In red.  Pillar box red.  Sexy lingerie red.  Very very red.

While the 64Gb Solid State hard drive would have been an awesome inclusion, for the extra $1000 I just couldn’t do it.

Out of Box experience.

It comes in an XPS sleeve that is actually pretty good quality, down to magnetic fasteners and neoprene sides.

Further investigation revealed a folder to keep the CDs and manuals.  It looked something like an executive folder you might take to a meeting.  A nice surprise in there was an XPS microfibre cloth.

The first thing I noticed was the weight.  This is one very light machine.  Thin, small and light. 

Upon plugging it in, the screen struck me as being exactly what the doctor ordered for the 1024x768 blues.  It is clear, bright and crisp.  Also very thin!

Design, design, design

It’s the details. 

If you search for pictures of the M1330 you will always come up with a side profile but the coolness of the hinge design for the lid didn’t dawn on me until I saw it – no, until I felt it.

At the top of the keyboard are a set of controls to eject the CD/DVD, control the audio & playback etc.  These are not buttons per se, but little touch sensitive spots that glow when you touch them.  Very cool.

The XPS M1330 comes with Creative EP-630 Noise Isolation earphones that compare quite favourably to my standard work wear – Philips SHP805.  They have 3 sizes of rubber seal for your ear, dunno how they feel when used for extended periods yet.  This was a nice surprise.

...and there are other little supprises all throughout this machine.  Someone, somewhere put thought into the design of this machine and it shows.

Now, to uninstall the crapware…

Having had a bit to do with Dell over the years, first thing I always do is open Control Panel and uninstall the bloat.  I was pleased to see so little preinstalled on my machine.

I removed:

  • Google Desktop
  • Google IE Toolbar
  • Microsoft Works  (I have Office and didn’t want to pay for a redundant CAL, so Works is the only choice when ordering)

Things that may go if they show me the first sign of trouble, but can stay for now:

  • Dell Browser Address Error Redirection (whatever that is!)
  • Roxio Creator Home

So, what’s not to like:

There are a couple of minor things – so minor I only list them for completeness.  None of these are an obstacle to being very happy with this machine:

  1. When you eject a CD the sound is like strangling a pigeon. Don’t ask me how I know what that sounds like, it just does.
  2. Chipset does not support Intel VT.  I use Virtual PC a lot, but VMs run fine without it.
  3. The system comes with a 10Gb recovery partition.  This isn’t a worry to me with 250Gb but if I had gone for the 64Gb Solid State drive for the extra thou’ I would be nuking this straight away
  4. The battery in the media remote is tricky to seat properly. 

The Essential Stats:

Dell XPS M1330

CPU: Intel Core2 Duo @ T7500 2.2Ghz

OS: Windows Vista Business 32 Bit

RAM: 4Gb RAM installed – 3.5Gb Visible to 32bit OS

WEI:  4.0, broken down as follows

  • processor: 5.1
  • RAM: 4.8
  • Graphics: 4.0
  • Gaming Graphics: 4.5
  • Primary Hard Disk: 5.2

Video: NVidia 8400M GS w/ 128Mb RAM – 1280 x 800 x 32 on 13.3”

HDD: 250Gb WD SATA

Overall

Since it is only day 1 I can't be definitive, but this machine shows every sign of being a great developer PC.  Recommended. 

Wednesday, October 24, 2007 7:23:41 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, October 21, 2007

The SQL Server 2008 ("Katmai") CTP 4 VHD that was published to MSDN Subscriber Downloads last week is made available as a 4-part self-extracting RAR archive. 

It can seem to have an issue in while self-extracting.  As shown in the screen cap below is it looking for en_sql_server_2008_ctp_4_vhd_part_1_of_5_.rar: 

 

This is obviously wrong because a) part 1 is not a rar - it is in the exe, and b) the download is in 4 parts not 5.  So if you see this prompt, browse for en_sql_server_2008_ctp_4_vhd_part_2_of_4_.rar.

Likewise when asked for en_sql_server_2008_ctp_4_vhd_part_2_of_5_.rar browse for en_sql_server_2008_ctp_4_vhd_part_3_of_4_.rar

Finally when prompted for en_sql_server_2008_ctp_4_vhd_part_3_of_5_.rar browse for en_sql_server_2008_ctp_4_vhd_part_4_of_4_.rar.  You will not be prompted for a part 5.

Once you have done that, fire up VPC or Virtual Server 2005 and enjoy!

Also, don't forget:  You can check out the LiveMeeting events on the new features in SQL Server 2008 available through the Connect site.

Listening to: Aphex Twin, Selected Ambient Works, Volume II

Sunday, October 21, 2007 12:48:20 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [3]  | 
# Thursday, October 18, 2007

I have a ColorPlus monitor profiling spyder by what was formally marketed as Pantone and is now Datacolor and I profile my monitors regularly.

Today was the first time I have tried to profile it since I built my new dev workstation.  It turns out the (circa 2004) ColorPlus spider that has served me well so far is now in the legacy bin.  While it works great on Vista x32 with the XP driver it has not had signed drivers released for Vista x64.

This lead me to look at what was the latest news for loading unsigned drivers into Vista x64, since I only need the thing to run for 5 minutes once every couple of months I was hoping to see that there would be some BCDEdit trickery that may let me reboot into a non-standard config, generate an ICC profile and then boot back into "real" Windows.  Seems that option was supported on Vista RC2 and removed for the RTM.

What has this to do with Linchpin Labs?

Further investigation showed up the case of Linchpin Labs (who have a Willoughby NSW address, as well as Ottawa CA).   Linchpin released a widget called Atsiv that was itself signed and would let you load unsigned drivers through it. 

Things got interesting when Microsoft categorized Atsiv as malware. 

The Microsoft position on this is detailed in the Windows Vista Security blog, and the equally detailed response by Linchpin Labs is detailed on their site.  It's unfortunate that Linchpin do not have a blog because it would be interesting to contrast the comments on the MSDN blog to any they attract.

As for the comments it seems lots of folks think their obligation ends with complaining.  It may be fun to type crap on a message board, but my respect is reserved for the folks who put time into finding the solutions.

But, what seems missing in the discussion to me is that (depending on how you count the numbers) between 40 and 60 million copies of Vista have been shipped in 19 languages to 70 countries.  Only a slim slice of that huge number of users are the tech savvy / tech professional community who, generally speaking, keep technology and the internet working and profitable for the rest of the world.  I think it is right that security decisions favor the great unwashed masses rather than the techno-elite, who should be able to look after themselves.  A bit of perspective please people.

If you get to the bottom of the Linchpin Labs announcement you find the following:

  Linchpin Labs would like to suggest that Microsoft spend less time using debatable policy as a security mechanism, and spend more time actually tightening its operating systems.

Wha??  Isn't that what this is all about?  Driver Signing Policy is tightening the OS.  Other examples of Vista security enhancements include:

  • Restricted Services (service hardening)
  • DEP and NX, including supporting hardware-based DEP 
  • User Account Control (UAC)
  • Windows Defender / Windows Firewall / Windows Security Center (techies:  think of the 98% of the world; they need hand holding, OK)
  • Network Access Protection (NAP) 
  • Bitlocker and EFS
  • ActiveX Opt-In, support for EV Certs and anti-phishing filter support in IE7
  • ...

...and probabbly others.  Yeah I'd call this tightening the OS.

Back to my ColorPlus Spyder...

So, looking at my options:

  • Get a Mac.  Oh yes would I love to get a Mac.  hmmmm :)  But, desk space, power and brain cycles are at a premium at the moment.  Also being a entry-level product the ColorPlus is a Windows-only product so it would mean getting a new spider anyway.
  • Get a new Spider.  These are costly devices and not really top of my spend list right now.  Maybe one day.
  • Abandon the DRM-infested evil Microsoft empire, like some of the commenters (e.g. "Joe" et al) on the Vista Security Blog suggest.  Just try and have a 16-bit/channel colour accurate workflow in Linux.  I've been there (not recently, but as far as I can tell things haven't changed much) and it's not fun.  Just go and spend some a couple of weeks setting it up and let me know how you get on.  Send me a postcard.  Really.

Now for some real options:

  1. Email Datacolor and let them know that people are interested in Vista drivers.  Done.
  2. Install a copy of Vista x86, update to the latest vid drivers, calibrate the monitor, pinch the ICC profile, reboot into my "real" Vista x64.  It'll take 1hr tops.  I'll get to this on the weekend.

um, anyone want to but a second hand ColorPlus Spyder?  One careful owner, still with original box...

Listening To: The Polyphonic Spree, The Fragile Army

Update:  My ColorPlus is no longer for sale :-)

It turns out that in the ColorVision Knowledge Base (under Support Centre) there is an article that says:

ColorPlus users can download Spyder2express software from the colorvision website's support section, and run that software with a ColorPlus serial number and a ColorPlus Spyder. The latest versions of Spyder2express are compatable with Vista32 and Vista64.

I can confirm this works.  Spyder2express is a 120Mb download which is hefty since I only want the driver :-/  The ColorPlus is detected as a Spyder2 after installation and works as advertised.

...and would you believe their is a Mac version of ColorPlus 1.1 in the Knowledge Base that is not listed in the Support downloads.  I'm happy to be wrong anytime it works out for the best :)

Listening to: The Campfire Headphase, Boards of Canada

Thursday, October 18, 2007 10:09:42 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, October 14, 2007
It was great being able to have the opportunity to elucidate my thoughts on this matter formally at SQL Down Under Code Camp '07.

For completeness, here are my slides: The Zen of T-SQL SDU CC.ppt (128.5 KB)

I really enjoyed meeting so many nice and very clever folks.  Thanks to Greg and all involved in putting on the Code Camp, what a really great event!

For the record, the image is of Kasprowicz catching Pietersen at NatWest Challenge Final, The Oval, 2005.

:-)

Sunday, October 14, 2007 10:25:08 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, October 03, 2007
I'm just catching up on my feeds and saw Nick Hodge's post with his slides from the Australian Blogging Conference

Without the benefit of the associated naration they are still worth a look on the topic of business blogging.

Wednesday, October 03, 2007 8:54:39 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, October 02, 2007

I have been looking at company blogs to satisfy a mixture of professional and after-5 curiosities. The example I keep coming back to is 37signals.

The reasons they top my list are:

The product blog is a great read for hearing how to get the most out of their products. In their own words, Signal vs. Noise, a weblog by 37signals about design, business, experience, simplicity, the web, culture, and more.

For a tech R&D shop, this is about as good as I have seen.  I'd also welcome comments on other good examples that people like!

An honourable mention goes to Art. Levedev Studio’s Life and Incredible Adventures of Optimus Keyboard blog where you can keep up with the hardware development in what may turn out to be the last word in keyboards!

Tuesday, October 02, 2007 5:24:55 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
# Friday, September 21, 2007

I came across the following example in Inside T-SQL Programming, which I am digesting at the moment.  Actually it is credited to Steve Kass (technical editor):

SELECT OrderId, OrderDate
FROM dbo.Orders
WHERE DATEDIFF(day, '19000102', OrderDate) % 7 = 0

This query is to answer the question "Which orders were placed on a Tuesday?".  The query isn't particularly magic, but the idea behind it is as close to the zen of T-SQL as I can remember seeing:

There are 7 days between any two Tuesdays.  If we know one Tuesday (like the 2nd Jan 1900) we have all the Tuesdays since.

What a great mindset to take with querying.

Listening To:   Places like this, Architecture In Helsinki

Friday, September 21, 2007 11:44:04 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, September 13, 2007

Problem:

Sorry Adobe, parentheses are valid characters in a path.

Solution:

Luckily the work around is quite easy...

Check the 8.3 name of the x86 Program Files path in this listing:

c:\>dir /N /X
 Volume in drive C has no label.
 Volume Serial Number is BA64-04DE

 Directory of c:\

28/08/2007  01:04 PM            30,469 DXCORE~1.LOG DxCoreInsaller.log
27/08/2007  07:24 PM    <DIR>                       inetpub
28/08/2007  01:26 PM    <DIR>                       NVIDIA
28/08/2007  01:44 PM    <DIR>          PROGRA~1     Program Files
28/08/2007  01:42 PM    <DIR>          PROGRA~2     Program Files (x86)
27/08/2007  09:41 PM    <DIR>                       Users
28/08/2007  01:45 PM    <DIR>                       Windows

Creative Suite 2 will install and work if you actually type in the 8.3 name for the x86 Program Files path, like:

C:\Progra~2\Adobe

I wonder who is next...

Listening to: Northern Substructures compilation

Thursday, September 13, 2007 11:44:33 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 

First, some breif background:  My motherboard went belly up, electronic burning smell and all.  Power supply was suspect too.

So time to go shopping!

The new motherboard is the ASUS P5K Premium.

For the CPU I went with the Intel Core 2 Quad Q6600.

An important goal for me was this build was Virutal PC performance, and I am pleased to report it is doing just fine.

The WEI score is up to 5.3, broken down as follows:

Processor Intel(R) Core(TM)2 Quad CPU @ 2.40GHz 5.9
Memory (RAM) 4.00 GB 5.5
Graphics NVIDIA GeForce 6800 GS 5.9
Gaming graphics 2303 MB Total available graphics memory 5.3
Primary hard disk 107GB Free (149GB Total) 5.6

The most important change for me was installing the 64 bit edition of Windows Vista Ultimate.  So far I've not had any dramas with drivers and only the odd run-in with apps.  For this I have started a new category on my blog:  Who sucks at 64 bit.

It would be remis of me to not mention the great help that Kernel at KNK Professionals was.  He went to great lengths to make sure I had the hardware that I needed.  All while his wife was giving birth to their first baby!  Highly recommended.

Thursday, September 13, 2007 11:33:49 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, August 28, 2007
Why?  They are taking up space and not the latest editions.

How?  Just leave a comment on this blog post.  Include your email address if I don't know you :-)

The books on offer are:

Microsoft
Professional SQL Server DTS, Chaffin, Knight & Robinson
[link]
Introducing Microsoft.NET, by David Platt (famed author of Why Software Sucks)
[link] Taken!
Programming Microsoft SQL Server 2000 with XML
[link] Taken!
Microsoft SQL Server 7.0 Administrator's pocket consultant [link]
Microsft SQL Server 2000 Administration Readiness Review for MCSE Exam 70-228
[link]
Microsoft Visual Basic Design Patterns
[link]
Java
Java Servlet Programming. Hunter, Crawford.
[link]
XML, XSLT, Java, and JSP. A case study in developing a web application.
[link]
Java Enterprise in a nutshell, a desktop quick reference
[link]
Linux
Linux Routers, a primer for network administrators, Tony Mancill
[link]

Caveats: Some of these are a bit marked on the cover from normal wear and tear.  Original CDs are still in the book where applicable.  Email me if postage is required.
Tuesday, August 28, 2007 11:51:24 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [4]  | 
# Monday, August 27, 2007
Don’t underestimate the sly and insidious lengths Personal Firewall products in general, and Norton Internet Security 2007 in particular, will go to in fulfilling its goal of disrupting SQL Sever Management Studio.

That will be all.
:-)

Monday, August 27, 2007 4:56:39 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, August 15, 2007

For a limited time, members of CSharpZealot.com have access to some free Silverlight training content!  Here's how:
Easy!

Also, I'm impressed at how well the InnerWorkings bits integrate with Visual Studio during the training experience.  You should really check it out.

Now please keep in mind that Web 2.0 (and it's previous incarnation, Web 0.9) supports bi-directional time travel
  • Forward, at a pace of 1 second per second, same as daily life, really; and
  • Backwards at a rate of 20 yrs in, say, about 150 miliseconds.
That means that if you are reading this blog post some time in the future, this offer may be closed.  It's only open for a limited time, so get to it!  Don't be the last guy on the block to not know how to use the MediaElement and VideoBrush in Silverlight!

Mad props (that's what the kids say these days, don't ya know?) to Brian Madsen, btw, for keeping CSharpZealot the place to get your .NET love.

Wednesday, August 15, 2007 6:01:21 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, August 14, 2007
A friend of mine dropped me an email that asked the following:

So, I’ve been thinking more and more lately that I should make some better use of my spare brain cycles and train time by learning some coding. Do you have any recommendations for where a total coding newbie with no money and no copy of VS should start?

So I thought I would answer in a series of blog posts.  This is part 1.

The first thing is no money does not mean that you can’t have a copy of Visual Studio

The first thing to do is grab a copy of Visual Studio Express Edition.  These are supprisingly capable cut down versions of the real Visual Studio 2005.

Go for Visual Basic or C# - don’t think C++ or J# are particularly good places to start learning code.  Either is fine.  Really. 

Also, Visual Studio 2008 Express Edition is available in Beta 2 at the time of writing.  Visual Studio 2008 is awesome, but again not the best place to start imho.

Then grab Visual Web Developer Express and SQL Server Express

Also, if you think MCP Certification is on the cards, each MS Press training kit comes with a 90-day copy of Visual Studio Professional.

UPDATE:  There are some additional downloads to consider:

The second thing is no Visual Studio does not mean no .NET programming

#develop, or SharpDevelop is a free, open source development tool for C#, VB.NET and Boo.

It has a couple of limitations, but can be had for a tiny 8.2Mb download and dosen't carry some of the weight of Visual Studio while still keeping some of the look and feel.

Still have some spare bandwidth?

Grab the Windows SDK.  It's probabbly a bit above the beginner level but it represents an execllent reference to what is happening under the hood when you come to need to know.

Grab FxCop (NB: you may have grabbed this as part of the Windows SDK).  FxCop is a tool that looks at your programs and compares them to a set of rules for programming on the .NET framework.  This is a little bit of an advanced topic, but also is a really valuable learning tool for avoiding bad coding habits.

FxCop 101:  The default is to check your code against all the rules.  As a beginner you probabbly don't want this.

Source code control is an important practice.  Even for a single guy on a train.

For source code control I would recommend going with SourceGear Vault which is free for a single named concurrent user.  It's really easy to install and get going.

Unlike SourceSafe, Vault is backed with a SQL Server database for better performance and backup support, and also runs over SSL and can run over the internet.  Additionally it supports an Edit-Merge-Commit usage pattern in addition to SourceSafe’s Checkout-Change-Commit usage pattern – but that is a bit of an advanced topic so don’t get too distracted.  Just know that it’s there for later.

What Else?  I'd love to hear from anyone via comments here on this topic.  What other bits should people go and get for programming on day one.

Listening To:  DAT318 Applied ADO.NET Entities from Tech.Ed '07.

Tuesday, August 14, 2007 1:26:16 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [2]  | 
# Tuesday, August 07, 2007



If you are attending and wanna hang out, drop me a line via this blog.

Otherwise, see you next week* :)

* by which time I will be significantly smarter... ;-)

Tuesday, August 07, 2007 12:34:22 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, July 31, 2007
The CLR Add-In Team Blog has just posted a list of the 7 new features that they have included in Visual Studio Orcas2008 Beta 2.

Tuesday, July 31, 2007 11:49:06 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, July 19, 2007

This is the third of my posts about group policy for web developers [part 1] [part 2], and today's post is a from-the-trenches tail about how you can get 401.1 Access Denied as a result of applying group policy.

Mad props to Jimmie Russ and his post Access Denied 401.1 goes away temporarily after IISRESET, as it was his post that sorted my problem today.

As you will see in his post, it is possible to push out User Rights Assignment policies via a GPO that can define the following rights:

  • Log on as a service
  • Log on as a batch job
  • Allow log on locally
  • Access this computer from the network

The above list may not be complete, but it was these four that caused a problem in my IIS environment.

Two tell-tail signs that this is your problem:

  1. If you run the always awesome AuthDiag utility and it reports that certain local accounts (like IUSR_*) have rights missing, specifically the ones listed above.
  2. When you view the User Rights Assignment in Local Security Settings
    • The above four rights are locked (have a little lock icon instead of the "blue 1s and 0s icon") and are not able to be edited.
    • The above four rights are not granted to our local accounts (again IUSR_* et al)

Again, it may not always be exactly those four - what you are looking for are policies that will not allow your IIS accounts (as listed in the AuthDiag results) to log on.

If I had my time again, I would have cranked up the failed security events and listed them here, but my servers are working again and I like it that way so this can be left as an exercise to the reader :-)

As Jimmie said, the solution is to have these rights not pushed down to your web servers.  This can be by not applying them in your Default Domain Policy, or by putting your web servers in a seperate OU blocking policy inheritance.  If you're not sure, consult an expert.

Thursday, July 19, 2007 4:39:09 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, July 18, 2007
Sorry to anyone who is waiting for an IM, email, phone call or anything from me... there is a burning smell coming out of a server :-(

If you need me, I'll be double-checking that I have valid backups...

Update:  The acrid smell I mentioned above was in fact the smell of fresh just-out-of-warranty power supply.  I even had to wash my hair to get the smell out.  All is OK now.  :-)

Wednesday, July 18, 2007 5:08:36 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, July 12, 2007

How to start?
You will need several assemblies.  This is because to reach the level of decoupling that is desired, the pipeline has a certain pattern of dependencies between projects.  I’m not sure if I am subconsciously not objecting to it or actually actively like this now, was not always the way.

A pipeline?
Yes, you need one. 

What is a pipeline?
It’s a series of folders that live somewhere (does not have to be under your application's path) and each of the assemblies have their place in the structure.  The folders will look like this:

It’s probably a good idea to build one now in your project tree and set the build output as you go.

There is a graphic explaining the pipeline on the CLR Add-In team blog (with nice colours), it is also in the Orcas MSDN under the title: "Pipeline Development Requirements".  The MSDN one has the addition of lines to indicate the static dependancies.

I've chosen to show it differently in my graphics (don't say a word!) to indicate the order of it all coming together as well as the references.  In the graphic the arrow lines illustrate the dependancies between the projects.

Also, I make reference to the sample code throughout this post.  Download link is at the bottom.

Step 1: Define Contracts

The first step is to define the contracts in your contracts assembly and DTOs in your DTO’s assembly.

Your contract should be one interface per kind of add-in you will support.  These interfaces need to inherit System.AddIn.Contract.IContract and be decorated with System.AddIn.Pipeline.AddInContractAttribute.

Types in the DTO that you wish to pass over the boundary will need to be serializable.

Jason He’s example of a Paint.NET Add-In (link below) takes a different path, by adding the extra types in the Add-In View, adding more wrappers.  His approach may have advantages that I have not discovered yet, but it reminds me of some of the dancing you have to do when for example you have the same type in a Web Reference and a binary reference in the same project. 

My preference is then to make a behavior-free separate assembly that anyone can take a dependency on safely.  This is the reason for including a DTO project.  I also like having the DTO types there to do as a [DataContract] does in WCF.  This will allow the Add-In contract to remain static if the host side changes it’s implementations of the DTO equiv. types.

Change the project properties of the Contracts project to build to: ..\Pipeline\Contracts\

Also note, for types that take a dependency on the DTO project, set the Copy Local property of the reference to False.  This is to keep the pipleline path clean.  i.e. we don’t actually want a copy of the DTO assembly in the \pipeline\contracts\ path!  This will slow our discovery and generate warnings as the Add-In infrastructure tries to examine it for contracts.

Step 2: Host View and Add-In View

Add two new assemblies:  host view and add-in view
Each has a public abstract class that mirrors the contract interface but does not reference it.

Host view does not even need a reference to System.AddIn.

When building the Add-In View, be sure to:

  • Apply System.AddIn.Pipeline.AddInBaseAttribute
  • Set the project to build to ..\Pipeline\AddInViews\

Step 3:  Host Adaptor and Add-In Adaptor

Add two more assemblies:  host adaptor and add-in adaptor

Add-in adapter will have one AddinToContractAdapter class for each Add-In type and the Host adapter has one ContractToHostViewAdapter class for each Add-In type.

The AddinToContractAdapter descends from System.AddIn.ContractBase and implements the contract for the Add-In

The ContractToHostViewAdapter descends from the Abstract class in the Host View for the Add-In.

Set the build output path of the Host Side adapter to: ..\Pipeline\HostSideAdapters\
And set the build output path of the Add-In Side adapter to: ..\Pipeline\AddInSideAdapters\

The purpose of these adapters is too marshal calls between the instances of your IContract's and should just look like wrapper code.

Step 4: Build the Add-Ins

Every Add-In needs to take a dependency on the Add-In View project and the DTO project.  Be sure to set their Copy Local = False in the reference properties.

Each Add-In also needs to descend from the abstract class in the Add-In View project, implement overrides, and to be decorated with System.AddIn.AddInAttribute.

The AddIn Attribute is the key to how the Add-In will be seen by the host so pay attention to the parameters on the constructor.

Set the build output path of each Add-In to: ..\Pipeline\AddIns\<addinName>\

I should mention that the Add-In's in the sample code below are just stubs to show the complete loop.  The Book Library Add-In returns empty objects of the prescribed types, the other two throw an Exception.  This is to show error handling.

Step 5:  The Add-In Host

Take a reference to the Host View and Dto projects, this time it is OK to have the reference Copy Local.

In the attached example the Book Library add-in returns empty objects of the designed type, however the other two (DVD Library and CD Library) throw an Exception for each operation. 

By the end of the process, the project will look like this:


Trouble shooting & Error Handling

Just skiming over this topic, but it is wise to wire up a handler to AppDomain.UnhandledException for the app domain that will run your Add-Ins, and Application.ThreadException (Windows Forms examples) as well as wrapping calls into the Add-In with a Try... Catch block. 

If you are trying to work out why your AddIns are not being discovered, remember that:

  • AddInStore.Rebuild()
  • AddInStore.RebuildAddIns()
  • AddInStore.Update()
  • AddInStore.UpdateAddIns()

...all return an array of strings that can be examined to determine how the AddIn discovery went.

Source Code:

The source code for this example is available for download from the following link:

LibraryAddInDemoCode_deepdark.net.zip (152.81 KB)

It requires Visual Studio Codename Orcas Beta 1.

Summary:

There are a couple of steps to implementing the new System.Addin stuff, but none of it is hard!

...and considering that it replaces a lot of very untidy and error-prone Reflection code that we had to do in prior versions of the framework I think this is a great addition to the toolbox.

This post is not meant to be a hardcore reference, just the total of my experience with this technology to date.  If you have any feedback please don't hesitate to contact me by email or leaving a comment on this post.

Sources:

Listening to: The Chillout Sessions 3

Thursday, July 12, 2007 5:18:15 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, July 11, 2007
I think this question is really suited to two kinds of people:
  1. Criminally insane.  Reckless to a point considered, well, imprudent. :-)  You lick the top of 9V batteries; you chew on tin-foil.  You cut your toe nails with a Leatherman.  You bank the farm on a technology that is still moving because pain is your friend.
  2. People who may ship a product before .NET 3.5 ships.  .NET 3.5 has some new technologies that I am going to want to use.  Three that are immediately relevant are: new Active Directory bits, System.AddIn, and the goldern haired child, Linq.

These are bits that (esp. Linq) I want to bake in.  Right now I don’t want to code up bits that I know I am going to have to rip out soon in order to replace with the richer platform.

My ship dates are uncertain… if the product name is anything to go by Orcas is at least 6 mths away.  The real question in this post is how to mitigate the risk of being ready to ship before the platform is, and what to keep an eye on.

Please feel free to leave a comment or email me if you have clues for the above question :-)

IIS 7 & Longhorn Beta 3 already has a Go Live license.  I believe them when they say it is good quality, and I believe them when they say it may still change.  Is a similar license something that we may see for .NET 3.5 as more betas or CTP’s become available?

UpdateFeb 27 2008 is looking like the launch date for SQL Server 2008, Visual Studio 2008 & Windows 2008.

Wednesday, July 11, 2007 2:34:36 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, July 03, 2007

I have been noticing that CodeRush / Refactor Pro! are playing up every so often my shiny (well, dusty) new Vista PC.

The symptoms are minor, but annoying when you have your fingers trained :-)  Basically Smart Cut / Intelligent Paste stop working.

Turns out, the solution is on the Expert options:  Startup \ Re-register CodeRush commands with Visual Studio on next startup.  Easy!

...Then you can have all your pretty refactoring graphics back!

Tuesday, July 03, 2007 2:21:07 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
It became clear to me during my last blog post on the .NET landscape that it was going to grow into more than one post. 

Framework Versions

One fact that is important to note about the graphic in that post, and it was the catalyst for me making the drawing, is that the .NET 3.0 and .NET 3.5 frameworks do not supersede .NET 2.0 but augment it.

What I mean by this is if you were to look into your %WINDIR%\Microsoft.NET\Framework\v3.0 folder you do not get a new System.Data.Dll or System.Web.dll.  Instead you see the folders for:
If you look in your %WINDIR%\Microsoft.NET\Framework\v3.5.xxx\ (still beta at time of writing) the main thing to note here is a new csc.exe and vbc.exe.

So what do you get with .NET 3.5 & Visual Studio 2008 (codename "Orcas")?

Update:  Please also check out Daniel Moth's whole bunch Orcas posts, and his run-down of the new bits.

...and last but not least, the golden haired child, LINQ...

...and for everything that I have missed, or is not in the beta bits yet, grab the Orcas overview whitepaper.

What is .NET 3.5 going to do to 3.0?

It seems it has to do with Green Bits and Red Bits (source: Daniel Moth).  In other words, .NET 3.5 will also include SP1 for .NET 3.0 and SP1 for .NET 2.0.

Tuesday, July 03, 2007 9:11:18 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, July 01, 2007
When I started playing with LINQ, I needed to get some clarity on this in my mind, so in the spirit of Linnaeus, Mendeleev and Gell-Mann, I put together a graphic that showed the generations of the various bits, and after talking with friends thought it was worth sharing:

UpdateDaniel Moth has a better graphic for the same data on his blog first.  Shame, not an image map. :-)

Mohammad Adil Akif also has a version in his blog.

...This is the blog version - the original form was a Post-It note.
...And in the spirit of Web 0.9 (which came before Web 2.0 :-) the graphic is an image map :-)

I know there is much more coming, like the Dynamic Language Runtime, Domain-Specific Language tools, Silverlight, and so on.   I've also chosen not to call out the versions of Team System, both in the interest of clarity.
Sunday, July 01, 2007 11:51:05 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
# Wednesday, June 27, 2007

Today's post is about a nifty little trick that I have seen done with search text boxes on sites over the years and I decided that it had to be in my toolbox too.

What we are going for is a search box that looks like this when the page loads:

...and looks like this when the user clicks into it:

This technique seems to mostly be applied to search boxes, and I can see the benefit in that.

The post that follows is the amalgum of many VS-A's

To get this done, it is a bit of CSS to style up the inactive and active state for the text box, and a tiny bit of Javascript to tie it together.  I'm using the term active and inactive not in any technical sense, just to describe the two styles that are applied to our text box in response to the user activity.

(assuming the rest of the page is a drab #f0f0f0 in colour...)  These are the two style rules that we are using in the images above:

.inactiveSearchBox
{
    background-color: #f0f0f0;
    border: solid 1px #ffffff;
}

.activeSearchBox
{
    border: groove 1px #d9d9d9;
    background-color: #ffffff;
}

The markup for the input box is then as follows:

<input type="text" class="inactiveSearchBox" id="SearchStrng" 
   value=" Search Here"

   onFocus="this.className='activeSearchBox'; if(this.value==' Search Here')this.value='';" 
   onBlur="if(this.value=='')this.value=' Search Here';this.className='inactiveSearchBox';"
/>

As you can see it all happens in the onFocus and onBlur events of the textbox.  When the text box gets the focus it sets the class to be our activeSearchBox style and clears our standard text.  The onBlur event restores the default value if the user did not enter anything and sets our style back to the inactiveSearchBox style.

Glossary:

VS-A, n. View Source, followd by an "Ah!". 
See also: VS-****.

Listening to:  Former co-workers :-)

ASP.Net | CSS | Geeking Out! | UX
Wednesday, June 27, 2007 11:32:32 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
# Friday, June 22, 2007

You can do this today, like in 10 minutes...

OpenSearch is a format for describing how your site is searched, and optionally for adding Search elements to other formats like RSS. 

Auto-discovery of OpenSearch description documents is done via a link in your HTML head like so:

<link rel="search" type="application/opensearchdescription+xmltitle="My Site" href="http://www.mysite.com/open-search.xml" />

The OpenSearch xml document is interpreted in the browser to add extra search providers in the integrated search function as so:

The contents of the file can be short or it can be long.  A bare bones example may be as simple as this:

<?xml version=”1.0encoding=”UTF-8?>
<OpenSearchDescription>
   <ShortName>My Site</ShortName>
   <Description>Search My Site</Description>
   <Url type="text/html" template="
http://www.mysite.com/search.aspx?terms={searchTerms}"/>
</OpenSearchDescription>

The spec gives another simple, and one much more detailed example document.  The IE blog also goes into some detail... but in true internet fashion, View Source is the quickest path to an example :-)

Security?

The bad news is, as of current browsers at time of writing (IE 7.0.6000.16473, Firefox 2.0.0.4) it seems controls are quite lax around what search template you can include, I had no problems setting the URL in the search template as being a completely different site!   

While it would be completely hilarious to posion someone's search bar as a prank with the following three facts...

  • IE stores the search settings here: HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\SearchScopes
  • FireFox stores them in the filesystem: C:\Documents and Settings\<winprofile>\Application Data\Mozilla\Firefox\Profiles\<mozprofile>\searchplugins
  • (sounds like google, not work safe)
I would ultimately like some control here.  I can't see anything in Group Policy for enforcing/allowing/denying new search providers.  I'd like to add one to all PCs for my internal Sharepoint site for example.

DasBlog

Tangentally, If you are looking for the file to edit to add a new link url to a dasBlog site it is:

\dasblogce\themes\*\homeTemplate.blogtemplate

Listening To:  Sonic Youth, Daydream Nation

Friday, June 22, 2007 5:11:55 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 

OK, let me lay it out for you a la the Lost secret clues...

Thinkaboudit people, when have you seen us both in the same room?

The similaraties (*caugh* both of them) are really just too numerious to ignore!

Friday, June 22, 2007 3:30:39 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, June 13, 2007

Yes I have better things to do but no I could not help making more LolCats - this time no Tech.Ed

 

Linkage: ICanHasCheezburger & Teh Cats

I am going to be talking the Lolcat speek for the rest of the day and that is final.

Wednesday, June 13, 2007 2:06:36 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 

This is the second post on Group Policy for web developers.  Part 1 was about managing the local Intranet Zone for your AD network.  This post will be based on a similar scenario.  Specifically, when issuing certificates from a local Certification Authority, like Microsoft Certificate Services that ships in Windows Server 2003.

Modern browsers give you a more pretty warning system than they did last year when you view a site that do not chain back to a Trusted Root CA.  This is still an important warning and we don't want to condition people into just clicking yes every time they see it.

The first thing you will need to do (and like the last post, a certain degree of domain administrative Godness is required...) is get the CA's certificate from the CA.  Using Microsoft Certificate Services, you want to choose the option highlighted below:

This will prompt you to save the certificate file.  Do this, then delete it when you are done. 

Next we need to install the certificate into our client machines.  We will need a GPO.  You may use the one from the previous example or make a new one. Again the place in your AD to create this will vary.  For smaller sites adding at the the top level is fine, but hands off the default policy.

Navigate to Security Settings -> PK policies ->Trusted Root CA's as in the screen below:

Right-click on the Trusted Root CA's container and choose Import.  Here, browse for the cert file saved in step one and you are done!

Finally, here is some linkage to much more detail about Certificates in AD.

Wednesday, June 13, 2007 1:15:54 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 

OK, not a big cats person, but the lolcats meme has made it to Tech.Ed.

Frank Arrigo's post seems to be the epicenter, Brian has had a go too,  Plus more linkage here.

May I offer my contribution:

(And mad props to Frostdesign blog for the wholy unauthorized boosted image)

Wednesday, June 13, 2007 11:55:15 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, June 08, 2007

Some sites that you may have on your internal network, such as Virtual Server console, Sharepoint, ASP.NET sites of your own creation, and so on, can require your AD credentials to log you on.  Typically the browser will prompt you for them unless you add the site to the Local Intranet zone

This quickly becomes cumbersome as the number of users grows.  Everyone will have to add the URL to their Local Intranet zone manually and that spells work.

Internet Explorer

All the IE Zones, including Local Intranet, can be administered by Group Policy.  Where in your AD you create your GPO will depend on the scale of your operation, for smaller sites a GPO at the domain level is not a bad choice.  I'd caution against editing your default domain policy, consider creating a new GPO just under it.

Edit the GPO and browse to the Site To Zone Assignment List, inside the Internet Control Panel \ Security Page settings:

  

The UI will let you add IP addresses, FQDN's or http/https addresses, and which zone they will belong to.

One nice side effect of this to watch for is the users can now not change their zones via the IE settings.

FireFox

For FireFox, you are going to have to create/maintain an all.js in the %installdir%\defaults\pref\ directory.

This is just a plain text file that can contain settings in the FireFox Javascript format.  For Integrated Authentication you will need to add the following line:

pref("network.negotiate-auth.trusted-uris", "comma seperated site list");

Listening To: Kruder and Dorfmeister, the K&D Sessions, part 1

Friday, June 08, 2007 11:19:27 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, June 06, 2007

c'mon, it's still the 5th in someone's timezone ;)

With a tip of the hat to the fine people at Make, I present you with...

A solar powered Prius.  Now that is environmental.  White paper here.  Shame it still looks like a Prius.

Wednesday, June 06, 2007 11:08:17 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, May 31, 2007

There are not too many things I hate in the world.  Popcorn is one (no joke) another is the feeling you get when you discover something cool in the .NET Framework or Visual Studio and think: Damn!  Why didn't I find this sooner. I call it the Last one to the party Feeling.

Today, I'm talking about the SuppressMessageAttribute class (MSDN Link).

This attribute can decorate a class where you would like explicitly exclude a module matching a rule in FxCop due to a false positive.  Really it is no different to excluding the message in the FxCop project, but I think this is better because of how visible it is. 

When you exclude a message in the FxCop project it gets sucked into a black hole and you never see them again.  What if they are just a short term exclusion, like the old fav Microsoft.Design.AvoidNamespacesWithFewTypes - which may apply at the start of a project but not once it is off the ground.  Who is going to go and un-Exclude it from the FxCop project?

Also, this attribute takes named parameters, like Justification.  Again, FxCop lets you put a note in when excluding in the FxCop project but it gets lost to all but the most determined eyes.  Having the reason for the exclusion right there in the code means it has a better chance of getting on-going attention as it may not always be as valid as it is today through circumstance or refactoring.

This attribute requires you to define a symbol - CODE_ANALYSIS.  In NAnt you can add define = "CODE_ANALYSIS" on your CSC or VBC Task and/or define the symbol in your Project properties, depending on how you build:

Thursday, May 31, 2007 6:04:38 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, May 29, 2007

I've just got a couple of lessons from the last week to share around developing Office 2003 (and specifically Visio 2003) Add-Ins

I'm also trying to saturate this post with links because I have come up with a good size folder in my bookmarks for what started out to be a simple task.

  • Grab the PIA'sAnyone who wants to run the Add-In will need them.  Alternatively they can be installed from the Office Add/Remove/Repair under the guise of .NET Programmability Support, but in reality the user may not have the media or security access to do this.  Do NOT however ship the PIA's in your bits.  Ship the PIA's with your bits:  This means 2x MSI's.
  • Using NAant to automate the build with csc.exe & vbc.exe is suboptimal.  I'm keeping my project to one small assembly that depends on the PIAs, and also depends on another assembly that does the heavy lifting but has no ref to the PIA's.
  • Strong Name everything.  Well, strong name everything anyway, but when trying to pass of managed code as COM it is essential.
  • You cannot load a .NET DLL, even one with the ComVisibleAttribute on the Assembly or Classes, via the Office UI.  You just can't.  KB316723 gives an explanation.  This is because Office will try and register it the old regsvr32 way, which of course won't work.  To get a .NET DLL into the Macros -> Add-Ins list, you must write the registry entry under: HKEY_CURRENT_USER\Software\Microsoft\<office program name>\Addins\
  • This brings me to my next point.  KB316723 hints at it, but your setup must write a HKCU key not a HKLM key.  The Shared Add-In Wizard in Studio is ambiguous when it shows you this choice:

  • I know this may be contentious, but consider using VB.NET over C#.  This depends of course, but some parts of the Office object model make heavy use of Optional Parameters which C# does not support.  It has been noted elsewhere what Type.Missing can do for readability.  Having said that, it does vary greatly depending on where in the Office Object Model you are.
  • Spend some time with the Setup project that the Shared Add-In Wizard makes and test it.  Once you like it, reverse engineer it to a WiX script and feed that to your automated build.  For the record, you do that with:

Dark.exe –x path Debug/msi My.wxs
Candle My.wxs
Light My.Wixobj

  • To extra points when dealing with WiX-ified MSI's
    1. It's useful to note that the extracted (-x) resources take many forms.  DefBannerBitmap.ibd for example is just a bitmap.  I think it is easier to rename it to .bmp & tweak it in Photoshop than to add a new banner in Visual Studio.
    2. The Add-in reg setting mentioned in point #4 above references an assembly version.  Visual Studio tweeks this for you but your WiX script will be frozen at the time your Dark.exe'd it.  So don't auto-increment your assembly version numbers, or tweak you WiX script.  The choice is yours but your MSI must write the version of the Add-In DLL to the target machine's registry.

Listening To: Leftfield, Leftism

Tuesday, May 29, 2007 12:53:56 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, May 21, 2007

I think it is fair to say CruiseControl.NET has become synonymous with Continuous Integration in the .NET space.  In the recent DNR on CI* with Eric Sink and Martin Woodward it was the defacto choice for the discussion and with good reason.  CCNet is a great tool.

I just wanted to give a quick shout-out to Draco.NET which is also a CI server for .NET and while not having the broad featureset of CCNet I recommend it for smaller shops getting their first Continuous/Automated build together.  My two reasons are:

  • Supports Visual Source Safe, which like it or not is the Gateway Drug for source code control.  (To hear what I think of that go grab DNR #221 about 5min16sec in ;)  It also supports PVCS, Subversion and Vault.
  • It is so much easier to configure.  You have no options for reporting or postbuild steps, or overriding the build ID or RSS add-ons for.  CCNetConfig is essential for configuring CruiseControl.NET.  Draco.NET offers a pit of success for the folks new to CI.

The most compelling reason for CCNet over Draco.NET is Everyone else is using CCNet :-)

On the topic of DNR show #238 - Eric talks about Vault, but doesn't mention that you don't need to purchase a license when used for a single developer.  It is licensed by named accounts, so go get it and give it a go all you VSS folks!

*the best bit of the show is 11min45sec in... ;-)

Listening To: Ani Difranco - Revelling and Reckoning

Monday, May 21, 2007 8:06:12 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [2]  | 
# Tuesday, May 08, 2007

I was looking today at options for finishing a build with something other than an MSI or folder full of files:  An ISO file.

I am a fan of DaemonTools and associated add-ons.  Even if you're not planning to burn to disc, an ISO file can be a useful way of getting a bunch of files around the place.

First step was to grab a Windows binary of mkisofs from one of the various sources of cdrtools on the webNB:  It comes linked with Cygwin binaries.

This is a util that has its roots in the Linux/Unix world, so be prepared to scratch your head a bit if you are not familiar with the world of Linux/Unix command line tools.  Also if you are, don't be fooled by mkisofs following the naming convention of the other mk*fs tools.  It is really quite different.

In the *nix world, the online help is by the man ("manual") page system.  Basically, at your prompt you type man mkisofs for help with mkisofs.   This works in Google too!  The man page will be a useful reference, as will the less informative usage info you can get from mkisofs.exe -help

Having said all that, the following options are a really good place to start: 

Option Note
-J Enable Joilet (you want this)
-R Enable Rock Ridge (you want this)
-V diskname Set a volume label
-o filename.iso Set the output ISO file name
-graft-points allows "=" syntax in pathspec.  More on this below...
-m "*.tmp" Exclude files from the image by pattern

mkisofs takes paths to add to the ISO file as parameters, and by default all these are stacked under the root of the disk image.  If this is not what you want then you should enable graft points.  This option will allow you to make folders in your ISO image for each of the folders you are adding to the disk.

For example, the following pathspec will create two folders on the CD, one called Windows for the contents of the bin folder, and one called Documentation for the contents of the doco folder:

Windows=D:\build\windows\bin\ Documentation=D:\build\doco\

So the complete command line for mkisofs will be something like:

"C:\Program Files\cdrtools-latest\mkisofs.exe" -J -R -graft-points -quiet -o f:\backup.iso -V backup -m "*.tmp" Windows=D:\build\windows\bin\ Documentation=D:\build\doco\

For extra points, you can automatically burn the ISO to a disk using the cdburn / dvdburn tool that ships with the Windows Server 2003 Resource Kit Tools.

A couple of reasons I'll suggest using this over using cdrecord.exe that comes with the cdrtools package:

  • The cygwin-based tools don't work as well with later Win32 like Windows Server 2003, they seem to not deal with the tighter security well.
  • The syntax of cdburn/dvdburn is much much easier!

An example of the syntax to burn f:\backup.iso to the blank disc in the burner g:\ is:

C:\Program Files\Windows Resource Kits\Tools>cdburn.exe g: f:\backup.iso -speed max

Also note that the cdburn will eject the disk once it has been burnt!  Keep that in mind if your CD drive is normally behind a door or cage or something!

UPDATE:  This technique is also has some utility for backup-to-disk scenarios.  For example a backup batch file that made an ISO then burnt it to disk.

Listening to: Bend to Squares by Death Cab for Cutie

Tuesday, May 08, 2007 2:53:13 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [2]  | 
# Friday, April 20, 2007

Every so often I check that web service, just to see what it comes back with.... nothing yet ;-)

Nice to see it is still in Vista, my little magic 8-ball dialogue! 

I just wish I could control the default.

Friday, April 20, 2007 5:04:46 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, April 12, 2007

This script came out of a discussion here at the office around a product that isn't flexible or location aware in how it writes datetime values into the database.

This is also not paying attention to storing the date data in UTC or localtime or any of those concerns, just the semantics of storing whatever the date value happens to be.

What are your experiences with this?  Comments as always most welcome :-)

Example script follows:


/*
    You can use the following proc at the start of your app to see
    what the current date format SQL Server is expecting from you
    based on the default language selection set on your login.

    Look at the dateformat field in the resultset of this proc.

    Use this if you want to honour the regional selection that has
    been setup on a per-user basis on the SQL Server
    (login properties of each user)
*/

exec sp_helplanguage @@language

/*
    Otherwise, you may also override the language settings if your
    application code can only format dates one way.

    This will avoid message 241 at runtime:    
        "The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value."

    The 15th of Feb is a good example because there is no 15th month:
*/


SET LANGUAGE us_english
go -- dateformat is now = mdy

select cast('2/15/2003' as datetime) as US_1
go
select cast('15/2/2003' as datetime) as US_2 --Expect Msg 242
go


SET LANGUAGE british
go -- dateformat is now = dmy

select cast('2/15/2003' as datetime) as British_1 --Expect Msg 242
go
select cast('15/2/2003' as datetime) as British_2
go

You can grab the script here: 20070412.deepdark.net_dmy_mdy.sql (1.14 KB)

Thursday, April 12, 2007 10:52:12 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, April 04, 2007

An MVP they call Brian referred me to a new Blog/RSS Feed client called FeedGhost.

It scratches my itch for a feed reader that can sync between multiple PCs through a subscription service, but the most impressive feature I have found so far is the UI.  It has set a new high water mark for me in the smartclient space. 

Check out the screen shots - but once installed you realize the screenshots don't do it justice. 

The timing of this news couldn't be better for me because I was reading my feeds on my "Beta Bliss" laptop - Vista RC1 & Office 2007 Beta 2 TR, and office expired 1st of April so I was in the market for a new feed reader.  I love it when things just come together :-)

Wednesday, April 04, 2007 11:06:11 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, March 26, 2007

So I feel that my last post on pretty gray info bars in Photoshop could do with a second chapter :)

This is a pretty long series so I'll be breif - what follows is the rough outline of how to achieve the same result as a User Control in your Visual Studio project.  The advantage of this aproach would be to allow you to dymanically add text or other sparkle of your own creation :-)

Here's a sample:

Code follows :-)

namespace GrayBar
{
   public partial class GrayBar : UserControl
   {
      public enum GrayBarModes
      {
         GreenTick = 0,
         YellowBang = 1,
         RedX = 2
      }

      public GrayBar()
      {
         InitializeComponent();
      }

      protected override void OnPaint(PaintEventArgs e)
      {
         Graphics g = this.CreateGraphics();
         g.SmoothingMode = SmoothingMode.HighQuality;

         // Fill the whole canvas
         Rectangle wholeControlSpace = new Rectangle(0, 0, this.Width, this.Height);
         Brush controlFiller = new LinearGradientBrush(wholeControlSpace, Color.DarkGray, Color.LightGray, LinearGradientMode.Vertical);
         g.FillRectangle(controlFiller, wholeControlSpace);

         // Make icon in corner
         Rectangle iconSpace = new Rectangle(1, 1, this.Height - 2, this.Height - 2);
         Brush iconFiller = new LinearGradientBrush(iconSpace, Color.Gray, Color.DarkGray, LinearGradientMode.Vertical);
         g.FillEllipse(iconFiller, iconSpace);
         base.OnPaint(e);

         Font iconFont = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Regular);
         string iconText = "";
         Brush iconTextBrush = new SolidBrush(Color.NavajoWhite);

         float fontHight = this.Height; 

         // The Font, Text and Colour depends on the setting on our GrayBarMode property
         switch (GrayBarMode)
         {
            case GrayBarModes.GreenTick:
               iconFont = new Font("Wingdings 2", fontHight, GraphicsUnit.Pixel);
               iconText = "P"; // P == "tick" in "Wingdings 2"
               iconTextBrush = new LinearGradientBrush(iconSpace, Color.DarkGreen, Color.LightGreen, LinearGradientMode.Vertical);
               break;
            case GrayBarModes.YellowBang:
               iconFont = new Font("Arial", fontHight, FontStyle.Bold, GraphicsUnit.Pixel);
               iconText = "!"
               iconTextBrush = new LinearGradientBrush(iconSpace, Color.Orange, Color.Yellow, LinearGradientMode.Vertical);
               break;
            case GrayBarModes.RedX:
               iconFont = new Font("Arial", fontHight, FontStyle.Bold, GraphicsUnit.Pixel);
               iconText = "X"
               iconTextBrush = new LinearGradientBrush(iconSpace, Color.Maroon, Color.Red, LinearGradientMode.Vertical);
               break;
            default:
               throw new ApplicationException("Unknow Mode");
         }

         float iconTextXPos = (iconSpace.Width / 2) - (iconFont.GetHeight(g) / 4);
         float iconTextYPos = (iconSpace.Height / 2) - (iconFont.GetHeight(g) / 2);
         g.DrawString(iconText, iconFont, iconTextBrush, iconTextXPos, iconTextYPos);

      }

      private GrayBarModes _GrayBarMode = GrayBarModes.GreenTick;
      public GrayBarModes GrayBarMode
      {
         get
         {
            return _GrayBarMode;
         }
         set
         {
            _GrayBarMode = value;
         }
      }

      private string _MessageText;
      public string MessageText
      {
         get
         {
            return _MessageText;
         }
         set
         {
            _MessageText = value;
         }
      }

   }
}

C# | Geeking Out! | UX
Monday, March 26, 2007 9:26:02 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, March 23, 2007

My Pure CSS Tabs with ASP.NET 2.0 Master Pages post also apeared over on CSharpZealot.com where I just added a note about an alternate solution.  Copied here for completeness :)

There was an alternate solution using the CSS Friendly Control Adaptor toolkit for ASPNet 2.0 which renders the standard menu control as UL\LI tags rather than as tables

I chose to not go that route because I don't need the tabs to link to a sitemap datasource or anything cool like that - UL\LI in a master page was plenty good enough for me, however if you did want/need to link the same code to a sitemap then the CSS Friendly adaptors would be well worth looking into.

Listening to:  Wave of Mutilation: The Best of Pixies

Friday, March 23, 2007 12:35:46 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [2]  | 
# Wednesday, March 21, 2007

Just thought I'd make a post on what can be done to jazz up the average message bar or UI element.  In this example I'll be doing it by way of a Photoshop tutorial I hope everyone can follow.  As always, leave me a note in the commenst section below if this leaves any questions unansered.  It's a bit lengthy but I hope that is because I'm including enough detail.

Step 1: Start with a new image that will be the size of the UI piece you need.  In this case 500 pixels wide by 25 pixels high:

Step 2: Select the gradient tool (Keyboard Shortcut: G) and customize as follows (things to click on are highlighted in Red on the sample screen below):

  • Choose the Reflected Gradient mode from the toolbar
  • Drop down the Gradient picker and choose the Foreground to Background gradient

Sample screen:

Step 3:  Make a background

Select a background and foreground colour in the toolbox that match the look you are going for.  Today I am going for light gray and dark gray because as everyone known things that are made out of "technology" are gray!  :-)

Notice the lighter colour is above the darker colour - you can swap the foreground and background colour with the X key on the keyboard

Now click and drag your mouse from top of your image to the bottom.  You will want to hold the Shift key down - this makes sure your gradient is painted straight with regard to the edge of the image.  You may want to have a couple of tries at it to find something you like - remembering that you can start your drag from the canvas outside your image.

Mine now looks like this:

Step 4:  Adding a highlight

An image in Photoshop is made up of layers.  A discussion on layers is worth a whole book, but just do as I say you will be OK :-)  I'm saying this now because it is from here on dowm that layers come into play for our example.

Duplicate the layer that we made our gradient on by pressing Ctrl-J on the keyboard.  Watch the Layers window inside Photoshop when you do this and you will see a new layer being created.  Change the blend mode of this layer to be Differnece.  Don't worry if your gradient turns black - we'll sort that out in a second.

The Layers window will look like this:

Now:

  1. Invert the new layer by pressing Ctrl-I.  This should again change the look of your image but don't worry - few more steps to go yet.
  2. Press D on your keyboard to reset your toolbox colours to Black and White.
  3. Click the Add Layer Mask button on the Layers window to add a Layer Mask to our new top layer
  4. Press Ctrl-Backspace on your keyboard to fill the layer mask with the background colour - Black.  This has the effect of making our new later not show at all.

So what is the point of making a new layer and then hiding it?  Well, we don't want to hide all of it - now we will make a small piece show through the Layer Mask that is hiding the Inverted copy of our gradient.  I am choosing to show a circle but you can play with different shapes.  To do this:

  1. Select the Elliptical Marquee tool from the tool box.  This one is hiding behind the rectangular marquee tool.  Press Shift-M to switch between the available types of marquee until you find the one with the circle icon in the toolbox.
  2. Hold down the shift key to force the Elliptical Marquee to make only circles, not an oval or ellipse, then click and drag over the left side of yoru top layer to make a circle.
  3. Press the X key again to swap the Foreground and Background colours agian - now White should be the background colour.
  4. Press Ctrl-Backspace again on your keyboard to fill our little circle with White.  You should now be seeing the inverted gradient only in the circle.  That is what the layer mask is doing for us - Where pixels are White on the layer mask, the layer it is hiding will shine through.  While pixels are Black on the Layer Mask the associated layer will not be seen.
  5. Right-click our top layer on the Layers window and choose Blending Options.  Choose Bevel and Emboss and then tweak the sliders to taste.  Here's what values are working for me today:

By now our graphic will look something like this:

Step 5:  Adding Modes

Here I'd like to use the same graphic for Error, Information and OK messages.  I'll use System.Drawing to actually paint the message text onto the image on a form, but for now I just want three states for the message that I can choose from.

Press the T key on the keyboard to choose the Text tool on the toolbox.  I'm now going to set the foreground colour to a nice blue, click above our new circle and press type a question mark: ?

You will need to change the font face and font size on the toolbar to suit.  Once you have what you like click the Tick button on the toolbar to save this question mark as a new text layer.  NB:  Using the text tool you can always come back to this layer and change it.  I have also added a Drop Shadow to my text layer using the Blending Options menu item again, but this is just down to personal taste.  Try it and see what you think.

Now my screen looks like this:

Notice that all the layers have an Eye icon in the first column.  This is so you can show or hide whole layers at a time.  This will become important shortly!

Now hide the Question Mark text layer and add two more:  one for the famous Red X and another for a Green Tick.  Hint:  There is a tick symbol in the Marlett font under the lower case b key.

Step 6:  Create final images

Remember what we said about showing and hiding individual layers?  Here's where it becomes useful.  We are going to save this image three times.  Each time we save it we will make a different combination of laters visible before saving. 

So first make sure your two gradient background images are showing plus only one of the text layers.  Start with showing the Question Mark text layer and not the Red X layer or the Green Tick later, then choose Save For Web from the File menu.  Choose a file name like InformationBar_Question.jpg.

Your choices for GIF vs. JPEG vs PNG, compression etc are all for the purposes of this exercise personal taste.  Depending on if the image will end up on a web form or a windows form your choices here could matter a lot!

Now repeat the process showing only one other text layer at a time and naming accordingly.

Here are my three final images:

InformationBar_Error.gif:
InformationBar_OK.gif:
InformationBar_Question.gif:

Advanced Class:  A few extra things to try

  • Make a new Gradient out of as many colours as you want.  Ninja skills in making a gradient is the art of being able to make something look like is concave or convex on the page.  Most important in this is making sure all UI elements on a page cast the same shadown (direction, colour and spread) and apear to be lit from the same direction.
  • To keep things on-brand, grab existing on-brand grapics and CSS sheets and stealresearch colour information on them. 
  • Use the sRGB colour space when targeting the web.
  • Save your master image as a PSD file to preserve the layers and make it easy to maintain if things change in the future. 

Listening to:  Perry Farrell - Song yet to be sung

Wednesday, March 21, 2007 12:55:20 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, March 19, 2007

I've been looking for a nice graphical representation of the access modifiers.  Couldn't find exactly what I want so, with the help of the very cool class designer in Visual Studio 2005 I have done my own.


RED means public access from even outside the project
BLUE here is protected access, for visibility in classes that descend from the class with the declaration.
GREEN represents friend access, for visibility in other classes in the project.

The one to note is FleaCount:  Protected Friend is the union of both Protected and Friend.

Monday, March 19, 2007 6:36:36 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 

Today's link propagation is for a page called: patterns & practices Security Checklists Index over at MSDN:

http://msdn2.microsoft.com/en-us/library/ms998392.aspx

This page describes itself as:

This page provides an index of patterns & practices Security Checklists organized by categories using multiple views.

It's slightly dated, but still current.  One for the bookmarks.

Does anyone have any other .NET checklists they can share?

Monday, March 19, 2007 1:24:20 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, March 16, 2007
...snipped from a discussion earlier today with someone who should know about C#!

btw, I found one conclusive reason as why to use C# over VB.Net when doing unit tests with NMock
in C# the line is:

Expect.Once.On(mockFetcher).Method("GetDatabases").Will(Return.Value(mockReturnValue));

in VB it is:

Expect.Once.On(mockFetcher).Method("GetDatabases").Will(NMock2.Return.Value(mockReturnValue))

Return is a NMock2 type as well as (with caps) a VB reserved word!  so you have to add a qualifier.

taking into consideration the semicolon that's 6 extra keystrokes!

Friday, March 16, 2007 5:23:05 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, March 08, 2007

It is probabbly wise to remember domain rules in the database when considering Intent Insurance.

A common scenario for a check constraint is to ensure the range of values in a field in cases where no foreign key constraint is available to constrain the values.  The typical example is the case of a [State] field, where a check constraint on the table may look like:

[State] IN ('NSW', 'QLD', 'VIC', 'ACT', 'TAS', 'NT', 'SA', 'WA')

To contrast this with the foreign key constraint, you may be guided by personal taste or circumstance to not create a lookup table of States since it is not expected to change any time soon and would then require a JOIN every time we needed to see the State with any address. 

Now to the point of the post, I just came across an example that is worth mentioning.  Consider the following simple and neatly anonymous table of clients:

Imagine a business rule exists as follows:

  • If this client is known to us by an online referal, they must have an email address
  • Any client, online referal or not, can have an email address

You would naturally expect this rule to exist programatically in the presentation tier.  The Intent Insurance mindset would then be to also add a check constraint to the table:

([online_referal] = 0) OR ([online_referal] = 1 AND [email_address] IS NOT NULL)

And there you have it, in one line another little parachute in the application asserting your intent.  Sleep a little easier tonight :-)

Thursday, March 08, 2007 9:47:03 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, March 06, 2007

Some times I just clap when I'm excited.  It's a bit Rain man-has-spoken.  Maybe I was stung by a bee when I was a child, I can't explain it. I clapped for the Litware HR overview doco.

According to SaaS Sample Application.pdf, the following bits that are required:

  • Windows Server 2003 SP1 or R2
  • IIS 6.0
  • SQL Server 2005 Full Cream or Express editions
  • Microsoft Visual Studio 2005 Pro or Team Suite (recommended)
  • .NET Framework 3.0
  • Visual Studio 2005 extensions for .NET Framework 3.0 (Windows Workflow Foundation)
  • Visual Studio 2005 extensions for .NET Framework 3.0 (WCF & WPF), November 2006 CTP
  • Enterprise Library for .NET Framework 2.0
  • Active Directory Application Mode (ADAM) SP1
  • Guidance Automation Extensions
  • Guidance Automation Toolkit  

...and that is all that you need to take over the world.

ADAM is what jumped out at me.  I have managed to not have much exposure before now however get the feeling ADAM and I are going to get a bit better aquainted before this exercise is done.

I'm building up a VPC image with all the bits now and I'm taking Friday off work to sit at home with my DeLonghi Metropolis 1385 Espresso machine and the coolest SaaS guidance around and I'm not coming out until I have a business plan or my head explodes.  (I'd say you will know by Monday, if you are curious)

Tuesday, March 06, 2007 1:11:34 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [4]  | 

Amazing.  I just noticed that the term SaaS has only had the most fleeting of references on my blog thus far, and then only in jest.

This is amazing to me because as anyone who has had a yarn with me about the ISV space over a couple of glasses of wine knows its hard to shut me up about it.

What does this prove?  I don't blog after a couple of glasses of vino.  :-)

Situation rectified 

Listening to: Kings of Leon

Tuesday, March 06, 2007 12:47:50 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, February 27, 2007

Just a follow-up on my post of yesterday about the intent of exposing a read-write property of an Array/Collection type.

Practical Guidelines and Best Practices has the following guidance (i'm paraphrasing)

13.13 To protect the state of a backing var for properties that return arrays, consider

get { return DirectCast(_arr.Clone(), string()); }

which is good protection, but less efficient.  Or, provide indexed access to the array by an indexed property or function.  Getting close...

13.14 Properties that return a collection should be read-only to prevent clients replacing the whole array with a new one, or with a null reference as that could break assumptions elsewhere in the class. Disco! 

Thanks lads!

Tuesday, February 27, 2007 8:53:36 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, February 26, 2007

This one came up in discussion last week and could be worth mentioning.

Consider the following property:

private List<SchemaAttribute> _attributes = new List<SchemaAttribute>();
public List<SchemaAttribute> Attributes
{
   get
   {
      return _attributes;
   }
   set
   {
      _attributes = value;
   }
}

NCover/NCoverExplorer reliably inform me that this property has only 50% coverage
in my tests.

By hereto unexplored forces of nature, every consumer of this class calls
.Attributes.Add()

or, itterates over it as so:
foreach (SchemaAttribute element in instance.Attributes)
{
   // ...
}

The keen eye will notice that neither of these ways to access the property actually hit the setter! 

Two possible paths present themselves:

  1. Write a test that just exercises the setter.  This seems to me pointless. 
    If we are to consider that our tests can serve to express our intention
    in a repeatable fashion, what is our intent?  To see if a Generic List still works?
  2. Consider makeing the property read-only.  Including braces I could own three lines less code.  Yay!
    And also now I have had cause to think about it, it's not my intention that the
    List be set as a list, for this class it just dosen't make sense right now.

Next step?  Consult Francesco & Giuseppe!

Sleep.  The best 10 hours of the week.

Listening to:  Nick Cave and the Bad Seeds - Abattoir Blues

Monday, February 26, 2007 2:02:40 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, February 19, 2007

In my commute this morning I was listening to my weekly dose of DotNetRocks - Show 214 with guest Billy Hollis and Billy mentioned something on Agile to illustrate a point, and it has stuck with me all day.

He was referring to a presentation he attended where an advocate said he was writing 2 or 3 lines of unit test code for each line of production code.  Billy's objection to this is hardly a challenge to intuition: Are we getting 4x the value for 4x the code?

One of my metrics for the unit tests that I write is that they don't hurt.  Some can be a couple of lines long, some can be heavily copied-n-paste'd.  Customizing a CodeRush template is time well spent.  There are no wrong answers, however you get them in there is really OK.

It makes sense:  You're writing a unit test.  The aim is to isolate a gizmo of your choosing in your code and exercise it.  The cumulative weight of the unit tests should really function as an expression of your intent for the gizmo.  I outlined what I think of the high importance of naming your tests in a prior post.

Monday, February 19, 2007 4:48:15 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, February 16, 2007

I love finding little nice features.  I just discovered the following combination in CodeRush:

alt-UP/alt-DOWN - Change visiblility (public/private/protected/friend) of property, variable or class that the cursor is inside

I've got to hang around late tonight for a conference call with London (on a Friday night no less!) but finding that has made my day.

We should all try to remember the importance of little units of joy in the software we make.

 

Friday, February 16, 2007 3:23:00 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [1]  | 
# Thursday, February 15, 2007
WCF is at SDNUG tonight...

...and also came across it here today:

Image courtesy Gary Costa Pereira

[?] After Blog Mint:  Juval Lowy was great at SDNUG last night.  Not a semi-colon in sight!  The presentation was mostly about architecture with the IDesign method.  Well worth it. 

Also, Justin, if you're reading this... sorry about spilling beer on you at the Paragon :-)

Thursday, February 15, 2007 8:32:45 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, February 06, 2007

Some of the problems a modern cow developer has to face... (thanks Brian - keep posting the funnies)

My contribution:


WATERFALL:  18 months ago, one cow went into the milking shead.  The method was sound, but you don't need milk any more.

AGILE:  Only milk when necessary. 

EXTREME PROGRAMMING:  You have two cows.  They milk each other.

TEST-DRIVEN DEVELOPMENT:  Know the bucket before milking any cows.

OPEN SOURCE:  I have a cow, you and some other guy from Norway milk it on weekends or when ever you have some free time. 

CONTINUOUS INTEGRATION:  Your team of two cows checks-in to the milking sheads every day.  Everyone has access to the milk.  Everyone feels good.

SERVICE-ORIENTED ARCHITECTURE:  We agree a schema for a cow.  No one feels dependant on any breed of cow, but no one has actually seen a complete cow.

SCRUM:  There is a backlog of milk orders.  Cows decide how they are to be milked.  Every 30 days the cows, pigs and chickens agree on an amount of potentially shippable milk.  The pigs and chickens get to decide when no more milk is needed.

SaaS:  You don't own the cows.  You rent access to them and pay for it out of OpEx.  Owning cows is outside of core business - you just need some milk.

Tuesday, February 06, 2007 1:53:08 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, February 02, 2007

Got Build?

(sprint pending ;)

Friday, February 02, 2007 8:22:44 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, February 01, 2007

I love a good coincidence :-)  Couple of interesting expirations...

  • One of my credit cards expired today.  Not your problem I know, just saying...
  • The first Office 2007 betas expired today too.  If this stands between you and a productive morning in Outlook, grab the Beta 2 Technical Refresh and you will be able to the 31st of March.

*with apologies for the Dark Side of the Moon reference, I'm still on a buzz from seeing Roger Waters at the SuperdomeAcer Arena last week...

Thursday, February 01, 2007 1:04:52 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [2]  | 
# Monday, January 22, 2007

Just back from leave this morning... Got a new personal best in email collection

 

Monday, January 22, 2007 9:01:39 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [4]  | 
# Friday, January 19, 2007

This is part two in a series of posts about ASP.Net Controls.

ASP.Net Controls, Part 2: Composite Custom Controls - some assembly required

Now these controls are able to be designed to have some reuse and life outside one particular project.  The up side is that you can piece together odds and ends from System.Web.Ui.WebControls just how you like them, and as per normal the actual rendering to HTML is left to ASP.Net.

The down side is you just start with a class, descend from WebControl and piece it together in code.

Here's a bare bones sample to illustrate the concept, but first some notes:

  • Import System.ComponentModel for the attributes on the properties.  This is how they display in your Visual Studio properties window
  • Use actual controls as backing variables for the properties.  You want to be holding instances of the controls you will display in your class, and then abstract their properties behind your own properties.
  • CreateChildControls is where you assemble what will eventually be rendered down to the browser by adding to the Controls collection exposed by the base class.
  • Call EnsureChildControls.  A lot.  :-) 
  • This sample control no behaviour.  Use += / AddHandler to wire up your controls to event handlers.  Omitted for clarity.
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace MyProject.Controls
{

    public class CompositeControl : System.Web.UI.WebControls.WebControl
    {

        TextBox txtInput = new TextBox();
        Button cmdSubmit = new Button();
       
        protected override void CreateChildControls()
        {
            EnsureChildControls();

            txtInput.Text = DefaultText;
            Controls.Add(txtInput);

            cmdSubmit.Text = "Submit";
            Controls.Add(cmdSubmit);

            base.CreateChildControls();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            base.Render(writer);
        }

        [Category("Appearance"), DefaultValue("Enter text here")]
        public string DefaultText
        {
            get
            {
                EnsureChildControls();
                return txtInput.Text;
            }
            set
            {
                EnsureChildControls();
                txtInput.Text = value;
            }
        }

    }
}

Friday, January 19, 2007 2:55:26 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 

It occurred to me that ASP.Net has been a topic missing from my blog, so to rectify the situation I'm posting three pieces on Controls in the ASP.Net space.  Took me ages to get this straight in my own head so with any luck it will make sense here.

Part 1:  Web User Controls (ASCX files), the low hanging fruit

What better place to start.  These are the odd one out in the ASP.Net control space for a couple of reasons. 

  • While it is possible, they don't do reuse between projects well. 
  • They do have a drag and drop design time experience!
  • You drag them onto a page from the Solution Explorer, not the toolbox.

First thing to note is they have their own life cycle after Page_Load, and it feels a little like Server.Execute()

While they do have their own code behind class that inherits from System.Web.UI.UserControl, I try to not use too many properties on the class because I feel it gives a misleading impression in implementation.  Just say the thing has a text() property and in my Page_Load I set the text to something, well after Page_Load the thing can do what ever it wants to and then I have to go looking for what happened to my value for the text() property.

Re-use between projects requires some planning because they are not seperate from your web project, but re-use inside the same project is what they are best at.  Things like a navigational device, a customer lookup widget or something that makes an appearance more than once are good examples.  Pull them out, glue them together with a Web User Control, drop them back in.  Easy. 

Friday, January 19, 2007 2:00:54 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, January 17, 2007

Oddly enough, this blog post is to remind me of a discussion I had with a friend tonight about SOA;

Here's one to not tackle after pork, sausage, squash and cabbage (no, really! *burp*): Does it count if it is not over SOAP Web Services?  What if your services are in the same app domain as in a plugin architecture?

The benchmark I lean on here is:  If our systems agree on schema & contract over classes & data then we are on the path to SOA.

Which brings us back to Jean Paul de Sousa.  The story of the small ISV in the corporate space can be -to lean on a canonical example- recieving a requiment like: Here's our definition of "The Customer" <insert schema here>. 

The good news is for the ISV maybe I don't care how you store your customer, so long as the system boundaries talk with respect to the agreed on schema for a customer.  The bad news is for, again to pick on a common example, what if wearing the ISV hat I store the customer_name as one field, however "The Customer" definition has it as first_name & last_name.

As the ISV, the temptation is to split our customer_name field at the service boundary translation code on the first occurance of space, so that "John Smith" becomes "John" "Smith".  "Jean Paul de Sousa" however should be split on the second space! 

My ETL experience and ponderings, coupled with the non-trivial digestion task I am faced with, bring me to the conclusion that this isn't a new problem at all!  Just a new place for an old problem to live.  Awesome.  Schema and contract it is ;-D

Listening To: Almost Crimes by Broken Social Scene from You Forgot it in People

Wednesday, January 17, 2007 12:47:04 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [2]  | 

I'm just getting into the second week of some annual leave.  Note to my employer:  Don't let me remember just how... how... relaxing, yes!  that's it, relaxing annual leave can be, I digress...

Today's story is that for the sake of nothing more than the coffee was good and that else I would spend the day on the couch, I went to wire up a network in a friends store today.  It was also for the sake of making sure I could still handle on some of the basics like crimp RJ45 ends on CAT-5CAT-6 and so on.

I don't think my friend is able to get just what I get from it.   It's something like brewing your own beer and juicing your own oranges, something organic.  For four hours I got to get dusty in the problems of his business.  Very interesting.  He uses a paper diary even!

Consider this little thought experiment:  So your business involves printing peoples photos.  Way back in the day, the average guy shot 24 or 36 frames on some Kodak Gold and got the role printed at the minilab, because otherwise it was just a tin - it wasn't "photos" until you printed them.

Then the digital world hits and 10x the people own cameras, PDAs and phones.  Now each frame is a photo in its own right as soon as you take it!  You could print it on your inkjet, email it, post it to Flickr, show it on your ipod, show it on your media centre, show it on your mobile, et cetera...

Now so many more people are taking digital pictures, but instead of everyone printing every frame, about 15% of people taking digital images are making any prints at all.  Smaller slice of a bigger pie.  This wasn't lost on Agfa, Fuji are watching and it isn't lost on Kodak and Konica Minolta.  Time to give the business model a rethink... but how?!?  As a small business you may not get too many bites at it! 

(Love to hear any of your ideas - post a comment!)

Tangentally, this reminds me of a tech firm I once had chance to experience.  Management thought the one performance review form could be used for both a Sales Exec/BDM role and a junior network admin role.  Turns out that "Networking" means different things to these two roles.  Whoda thunk it?  *rolls eyes*

Sorry for the cryptic title, it's to subtly encourage your thoughts down an empirical path...

Listening To: spose iz Lily innit, a'rite?

Wednesday, January 17, 2007 12:01:59 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [1]  | 
# Tuesday, December 12, 2006

OK,  so I was trying to kick this Code Generation bent I have been on of late, but… opportunity knocked yesterday for a query where one of the possible solutions involved codegen and I was weak  :-)

 

So imagine we have some convieniently breif and neatly anonymized canonical example like the following table:

 

SELECT customer_id, order_id

FROM OrderCustomer

 

 

customer_id

order_id

1

32

1

33

1

34

2

821

2

831

2

851

2

861

2

871

2

911

3

1

3

2

3

3

3

4

3

5

 

Now imagine the project is to remove all the rows from this table, except the lowest number order for  each customer.  The first step is to write a query to exceptionalize these rows:

 

SELECT customer_id, min(order_id) AS AS LowestOrderID

FROM OrderCustomer

GROUP BY customer_id

 

customer_id

LowestOrderID

1

32

2

821

3

1

 

The next step is to select some string literals with the original query so that the result is valid T-SQL

 

SELECT 'DELETE FROM OrderCustomer WHERE customer_id = ', customer_id,

       'AND order_id > ', min(order_id) AS LowestOrderID

FROM OrderCustomer

GROUP BY customer_id

 

Tangentally the little unit of joy in this whole experience for me is that  the <Ctrl-T> keyboard shortcut is the same in SQL Server 2005 Management Studio as it was back in Query Analyzer. 

 

So, hit <Ctrl-T> to output the results window as Text, then F5 to return the results to get something like:

 

DELETE FROM OrderCustomer WHERE customer_id =  1           AND order_id >  32

DELETE FROM OrderCustomer WHERE customer_id =  2           AND order_id >  821

DELETE FROM OrderCustomer WHERE customer_id =  3           AND order_id >  1

 

(2 row(s) affected)

 

(5 row(s) affected)

 

(4 row(s) affected)

 

Select all the DELETE FROM statements and copy and paste them into a new query window, then F5 to remove the rows.

 

Look at the table to test the result:

 

SELECT customer_id, order_id

FROM OrderCustomer

 

customer_id

order_id

1

32

2

821

3

1

 

Tuesday, December 12, 2006 9:35:10 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 

This is something I have noticed in a lot of the samples around plugin architecture (for example).  The common theme is to reflect over the DLLs in an path and load the types that impement a certain interface.  Fair enough so far.  Once you have a collection of pointers to entry points you have plug-ins... but you also have an attack vector.

These examples need to flesh out the scenario of testing the plug-in for authenticity imho.

My gut feeling is I want an X.509 cert in there somewhere as a pre-shared secret, but I don't quite have the full picture in my head just yet, should that tie in with strong naming assemblies, or be seperate additional layer.  Suggestions welcome :-)

Tuesday, December 12, 2006 9:24:19 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, December 04, 2006
This is the last one in this current thread for a while :)

By the end of the last example we had code that would discover what stored procs were in a SQL Server database and generate a managed wrapper library that could be extended.

The next step it occured to me was to be then generate an assembly from this source and load it into the currently executing program.  The MSDN pages I have linked to have some good samples.

I'm adding this one to my toolbox of hammers looking for a nail.
Monday, December 04, 2006 4:21:23 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, November 27, 2006

(this post is an appendix to my prior post on Basic Code Generation with XSLT, because I forgot this bit the first time!)

I just wanted to expand on thsi line in the VB code part of the template:

Public Class DatabaseAccess
    Inherits ConvienientBaseClass

Including a (facetiously named) base class for the generated code was no accident.  It provides a good way to seperate the generated code from the human written code.  All the generated code should be the tedious, repetitive, error prone code.  Exception handling, transaction enrolement, logging etc should be implemented in the base class so it can be ripped out if need be and of equal importance; the generated code can be re-generated without clobbering any human written code.

But that isn't very .NET 2.0 now is it.  We can extend the concept of seperating the generated code from any human written parts by changing our template to generate partial classes:

Public Partial Class DatabaseAccess
    Inherits ConvienientBaseClass

 

 

Monday, November 27, 2006 10:00:59 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, November 24, 2006

This was meant as a "Part II" to my prior post on generating Text, HTML & more XML with XSLT.  The point for today's post is that source code files are text files.  The example I am thinking of is generating a library of VB.NET wrapper classes for the stored procedures in a SQL Server database.

(I've also ticked the Continuous Integration category for this post.  It wouldn't be hard to think of a scenario where a build process would generate a library from a reference database on the check-in of a stored proc script, then deliver the latest rev of the library to the developers, anyway...)

Step one would be fetch the meta data about the stored procedures, for example: 

SELECT procs.Specific_Name, params.Parameter_Name, params.Data_Type, params.Parameter_Mode
FROM
INFORMATION_SCHEMA.ROUTINES procs
LEFT
JOIN INFORMATION_SCHEMA.PARAMETERS params
ON params.Specific_Name = procs.Specific_Name
WHERE
procs.Routine_Type = 'PROCEDURE' AND
procs
.Specific_Name NOT LIKE 'dt_%'
FOR
XML AUTO

Once we add a document node to this, we will have a document that contains many element sets like this one:

  <procs Specific_Name="GetContactByID">
    <params Parameter_Name="@ContactID" Data_Type="nvarchar" Parameter_Mode="IN"/>
    <params Parameter_Name="@ContactGUID" Data_Type="int" Parameter_Mode="INOUT"/>
    <params Parameter_Name="@Found" Data_Type="bit" Parameter_Mode="INOUT"/>
  </procs>

I think that's all we need to get started.

Step two is to transform this data into VB.NET code.  For today's example it suits me to generate two files: 

  1. One will contain classes that wrap ADO.NET calls to the database
  2. The other will provide types that wrap properties for passing into and out of the first

The text of the first template is as follows

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="
http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="text" indent="yes" />
 
  <xsl:template match="/">

Imports System
Imports System.Data.SqlClient
Imports System.Data
Public Class DatabaseAccess
    Inherits ConvienientBaseClass
    Public Sub New(ByVal cn As SqlConnection, ByVal trn As SqlTransaction)
        MyBase.New(cn, trn)
    End Sub
   
    <xsl:apply-templates select="/database/procs" />
    
End Class
  </xsl:template>
 
  <xsl:template match="procs">
    '
    ' Wraps stored proc: <xsl:value-of select="@Specific_Name" />
    '
    Public Function Execute<xsl:value-of select="@Specific_Name" />(ByVal params As <xsl:value-of select="@Specific_Name" />Struct) _
                                             As <xsl:value-of select="@Specific_Name" />Struct
        Dim exec As New SqlCommand
        Dim param As SqlParameter
        With exec
            .CommandText =
"<xsl:value-of select="@Specific_Name" />"
            .CommandType = CommandType.StoredProcedure
            .Connection = MyBase.DatabaseConnection
            .Transaction = MyBase.CurrentTransaction
        End With
  <xsl:apply-templates select="params" /> 
        Try
            If Not exec.Connection.State = ConnectionState.Open Then exec.Connection.Open()
            exec.ExecuteNonQuery()
        Catch ex As Exception
            Throw
        Finally
            If Not exec Is Nothing Then exec.Dispose()
        End Try
    End Function
  </xsl:template>
 
 
  <xsl:template match="params">
        param = exec.CreateParameter
        With param
            <xsl:if test="@Parameter_Mode='INOUT'">.Direction = ParameterDirection.Output</xsl:if>
            <xsl:if test="@Parameter_Mode='IN'">.Direction = ParameterDirection.Input</xsl:if> 
            .DbType = DbType.<xsl:value-of select="@Data_Type" />
            .Value = params.<xsl:value-of select="@Parameter_Name" />
            .ParameterName =
"<xsl:value-of select="@Parameter_Name" />"
        End With
        exec.Parameters.Add(param)
 
</xsl:template>
 
</xsl:stylesheet>

And the text of the second template is as follows:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="
http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="text" indent="yes" />
 
  <xsl:template match="/">

Imports System
    <xsl:apply-templates select="/database/procs" /> 
  </xsl:template>

 
  <xsl:template match="procs">
'
' Parameters for method: Execute<xsl:value-of select="@Specific_Name" />
'
Public Class <xsl:value-of select="@Specific_Name" />Struct
   <xsl:apply-templates select="params" />  
End Class 
  </xsl:template>
 
  <xsl:template match="params">
   Private _<xsl:value-of select="substring(@Parameter_Name,2,string-length(@Parameter_Name)-1)" /> As Date
 Public Property <xsl:value-of select="substring(@Parameter_Name,2,string-length(@Parameter_Name)-1)" />() _
                                                                     As  <xsl:value-of select="@Data_Type" />
    Get
      Return _<xsl:value-of select="substring(@Parameter_Name,2,string-length(@Parameter_Name)-1)" />
    End Get
    Set(ByVal Value As <xsl:value-of select="@Data_Type" />)
      _<xsl:value-of select="substring(@Parameter_Name,2,string-length(@Parameter_Name)-1)" /> = Value
    End Set
   End Property
 
</xsl:template>
 
</xsl:stylesheet>

To my eye, these look more like VB.NET source files than XSLT templates.  That's because they started life as .vb files.  Then I renamed them .xslt and started inserting the XSLT tags in places where I needed substitution from the XML source. 

To emphasise the hybrid-ness (is that a word) of these files, I have highlighted the VB.NET parts blue and the XSLT parts green, rather than keeping the VB.NET syntax highlighting.

Some breif thoughts: 

  • The value of this to my mind is in not having to hand code *every* one.  You hand code one, then generate the rest - in theory this reduces the opertunity for bugs which should be the focus of the exercise. 
  • Maybe this may find a home in a long-running project to have this as part of the build process, or maybe as part of some tooling focused on small one-off
  • This are commercial products that do code gen based on XSLT.  I haven't used them, but they may well be better than my home-brew sample :-)
  • Maybe useful for trainers, or producting samples for demos etc.  I'm thinking now about times where there may be a need to generate side-by-side VB.Net, C# & Java sample code for example.
  • Also include comment blocks that are readable by NDoc!

[edit: added line breaks for formatting.]

Friday, November 24, 2006 10:58:13 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, November 15, 2006

I just thought it would be more sense to provide a link to the files mentioned in my last post.  Grab them if you are interested.

Wednesday, November 15, 2006 9:45:46 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, November 13, 2006

I've hacked on a little bit about XSLT and I think it's about time I added some more.  So this post will serve as the next instalment, and somewhat of an introduction to the uninitiated.

Lets say we were to consider the following data:

Position Horse Jockey
1 Delta Blues (JPN) Y. Iwata
2 Pop Rock (JPN) D. Oliver
3 Maybe Better (AUS) C. Munce
4 Zipping (AUS) G. Boss
5 Land 'n Stars (GB) J. Egan
6 Mahtoum (AUS) C. Brown
7 Yeats (IRE) K. Fallon
8 Activation (NZ) M. Rodd
9 Mandela (NZ) C. Williams
10 Glistening (GB) S. Seamer

As XML, it could concievably arrive like this:

<raceResults>
<finish result="1" jockey="Y. Iwata" originISO="JPN">Delta Blues</finish>
<finish result="2" jockey="D. Oliver" originISO="JPN">Pop Rock</finish>
<finish result="3" jockey="C. Munce" originISO="AUS">Maybe Better</finish>
<finish result="4" jockey="G. Boss" originISO="AUS">Zipping</finish>
<finish result="5" jockey="J. Egan" originISO="GB">Land 'n Stars</finish>
<finish result="6" jockey="C. Brown" originISO="AUS">Mahtoum</finish>
<finish result="7" jockey="K. Fallon" originISO="IRE">Yeats</finish>
<finish result="8" jockey="M. Rodd" originISO="NZ">Activation</finish>
<finish result="9" jockey="C. Williams" originISO="NZ">Mandela</finish>
<finish result="10" jockey="S. Seamer" originISO="GB">Glistening</finish>
</raceResults>

And that is fine, and may well even be useful.  The place where we should introduce XSLT is when we would like to do something with it like turning that XML into text, HTML, or more XML.

Text is an easy one to start with.  Consider the following stylesheet:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text"/>

<xsl:template match="/">
   <xsl:apply-templates select="raceResults"/>
</xsl:template>

<xsl:template match="raceResults">
position,jockey,horse,
<xsl:apply-templates select="finish"/>
</xsl:template>

<xsl:template match="finish">
   <xsl:value-of select="@result"/>,<xsl:value-of select="@jockey"/>,<xsl:value-of select="."/>,
</xsl:template>

</xsl:stylesheet>

When applied to our XML, it will produce the following result:

position,jockey,horse,
1,Y. Iwata,Delta Blues,
2,D. Oliver,Pop Rock,
3,C. Munce,Maybe Better,
4,G. Boss,Zipping,
5,J. Egan,Land 'n Stars,
6,C. Brown,Mahtoum,
7,K. Fallon,Yeats,
8,M. Rodd,Activation,
9,C. Williams,Mandela,
10,S. Seamer,Glistening,

The trick is first to not look for flow control in the traditional fashion (For loops, etc).  Instead the XSLT processor will treat it in the following manner:

  1. Start at the top of the source document - denoted with a /
  2. Every time you find a raceResults do what is in the raceResults template.
  3. (now inside the raceResults template) output the literal string: position,jockey,horse,
  4. (still inside the raceResults template) every time you find a finish, do what is in the finish template
  5. (now inside the finish template) Pick out the attribute called result, then pick out the attribute called jockey, then pick out what ever is contained in this element.  NB:  Attributes are denoted by the @

And that is it!

Now did you notice how literal text was handled?  All the bits of your output can live inside the template.  Now if we wanted an HTML representation we would use the following template:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html"/>

<xsl:template match="/">
   <html><head><title>Race Results</title></head><body>
   <xsl:apply-templates select="raceResults"/>
   </body></html>
</xsl:template>

<xsl:template match="raceResults">
<xsl:apply-templates select="finish"/>
</xsl:template>

<xsl:template match="finish">
   <p>Position <b><xsl:value-of select="@result"/></b>was <b><xsl:value-of select="."/></b>ridden by <b><xsl:value-of select="@jockey"/></b></p>
</xsl:template>

</xsl:stylesheet>

...and following exactly the same steps as the text example, the XSLT processor will output the following HTML:

Position 1 was Delta Blues ridden by Y. Iwata

Position 2 was Pop Rock ridden by D. Oliver

Position 3 was Maybe Better ridden by C. Munce

Position 4 was Zipping ridden by G. Boss

Position 5 was Land 'n Stars ridden by J. Egan

Position 6 was Mahtoum ridden by C. Brown

Position 7 was Yeats ridden by K. Fallon

Position 8 was Activation ridden by M. Rodd

Position 9 was Mandela ridden by C. Williams

Position 10 was Glistening ridden by S. Seamer

As you can imagine, it can be easy to get a stylesheet for HTML output that contains a lot of HTML markup!  The important thing to note in this example is that the HTML inside the stylesheet must be valid XML as well as valid HTML.  Note the closing </p> which would normally be optional in HTML is manditory here.

Now we get to the fun example:  Turning XML into XML :D

Why would we want to turn XML into XML?  For as many reasons as you have XML in your life!  Imagine turning the above document into its own RSS feed for example.

We could use the following template:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">

<rss version="2.0">
   <channel>
      <title>Race News</title>
      <link>http://www.horses.com/</link>
      <description>Live race results as they cross the finish line.</description>
      <language>en-us</language>
      <pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
      <lastBuildDate>Tue, 13 Nov 2006 17:45:00 AEST</lastBuildDate>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs>
      <generator>My RSS transformation</generator>
      <managingEditor>james@deepdark.net</managingEditor>
      <webMaster>james@deepdark.net</webMaster>
     
   <xsl:apply-templates select="raceResults"/>
  
   </channel>
</rss>

</xsl:template>

<xsl:template match="raceResults">
<xsl:apply-templates select="finish"/>
</xsl:template>

<xsl:template match="finish">
      <item>
         <title><xsl:value-of select="."/></title>
         <link>http://www.horses.com/lookup?<xsl:value-of select="."/></link>
         <description>Registered in: <xsl:value-of select="@originISO"/> .  Ridden by: <xsl:value-of select="@jockey"/></description>
         <pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
         <guid>http://www.horses.com/results/race6273-<xsl:value-of select="@result"/></guid>
      </item>
</xsl:template>
</xsl:stylesheet>

This example is the reason I took you so far down the page.  It builds on the key points of the prior two examples: 

  1. The output can mingle in stylesheet, so long as it is valid XML.  I hope you have noticed that the stylesheet itself is valid XML too.
  2. Again there are no flow control pieces.  In fact is is using exactly the same 5 step process I outlined for the first example (you guessed it, this was no mistake :)

The output is the following lovely RSS feed:

<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>Race News</title>
<link>http://www.horses.com/</link>
<description>Live race results as they cross the finish line.</description>
<language>en-us</language>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<lastBuildDate>Tue, 13 Nov 2006 17:45:00 AEST</lastBuildDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>My RSS transformation</generator>
<managingEditor>james@deepdark.net</managingEditor>
<webMaster>james@deepdark.net</webMaster>
<item>
<title>Delta Blues</title>
<link>http://www.horses.com/lookup?Delta Blues</link>
<description>Registered in: JPN .  Ridden by: Y. Iwata</description>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<guid>http://www.horses.com/results/race6273-1</guid>
</item>
<item>
<title>Pop Rock</title>
<link>http://www.horses.com/lookup?Pop Rock</link>
<description>Registered in: JPN .  Ridden by: D. Oliver</description>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<guid>http://www.horses.com/results/race6273-2</guid>
</item>
<item>
<title>Maybe Better</title>
<link>http://www.horses.com/lookup?Maybe Better</link>
<description>Registered in: AUS .  Ridden by: C. Munce</description>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<guid>http://www.horses.com/results/race6273-3</guid>
</item>
<item>
<title>Zipping</title>
<link>http://www.horses.com/lookup?Zipping</link>
<description>Registered in: AUS .  Ridden by: G. Boss</description>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<guid>http://www.horses.com/results/race6273-4</guid>
</item>
<item>
<title>Land 'n Stars</title>
<link>http://www.horses.com/lookup?Land 'n Stars</link>
<description>Registered in: GB .  Ridden by: J. Egan</description>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<guid>http://www.horses.com/results/race6273-5</guid>
</item>
<item>
<title>Mahtoum</title>
<link>http://www.horses.com/lookup?Mahtoum</link>
<description>Registered in: AUS .  Ridden by: C. Brown</description>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<guid>http://www.horses.com/results/race6273-6</guid>
</item>
<item>
<title>Yeats</title>
<link>http://www.horses.com/lookup?Yeats</link>
<description>Registered in: IRE .  Ridden by: K. Fallon</description>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<guid>http://www.horses.com/results/race6273-7</guid>
</item>
<item>
<title>Activation</title>
<link>http://www.horses.com/lookup?Activation</link>
<description>Registered in: NZ .  Ridden by: M. Rodd</description>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<guid>http://www.horses.com/results/race6273-8</guid>
</item>
<item>
<title>Mandela</title>
<link>http://www.horses.com/lookup?Mandela</link>
<description>Registered in: NZ .  Ridden by: C. Williams</description>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<guid>http://www.horses.com/results/race6273-9</guid>
</item>
<item>
<title>Glistening</title>
<link>http://www.horses.com/lookup?Glistening</link>
<description>Registered in: GB .  Ridden by: S. Seamer</description>
<pubDate>Tue, 13 Nov 2006 17:45:00 AEST</pubDate>
<guid>http://www.horses.com/results/race6273-10</guid>
</item>
</channel>
</rss>

I think this technique is going to be ever more important in the future.  Take in some SOAP, spit out some HTML.  Take in some XML from one API, spit it out as RSS.  A great tool for the toolbox.

Monday, November 13, 2006 7:22:02 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, November 07, 2006
So here is what I want from the perfect laptop.
  • 15 inch widescreen capable of 1600x1000 - good for coding.
  • Weigh no more than 2Kg
  • All the standard bits like WiFi, a Windows key & better support for Suspend than my aging Inspiron 1100.  I wanna be like a mac guy and just shut the lid of the machine and not worry about it.  With my Inspiron that would cause a fire.
  • 100Gb SATA HDD, 2Gb RAM, Dual Core, Vista Ready
  • Definately less than AUD$3000, closer to $2000 the better
Here's the kicker:  Convertable tablet form factor and it kicks the res down to 1125x864, or 1024x768 when flipped for tablet-like note taking and ad-hoc jotting.

One day I'm gonna be looking back on this post on such a machine and grin :)

Tuesday, November 07, 2006 6:41:08 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, November 06, 2006
Monday, November 06, 2006 1:34:22 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, November 01, 2006
I love it when things come together:
CodeRush and Refactor! - I'm a fan
I love a good keyboard too.

Here's a nice little plugin for Refactor! that can show available refactorings or metrics on the display of a Logitech G15.  Too cool!

Wednesday, November 01, 2006 6:33:20 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
I thought it was about time I refreshed my rules for what good error messages are:

  • Consistant.  This could be visually consistant in the case of message boxes, or if they are being logged to a file or database table then being consistant helps them also to be machine readable.
  • Informative.  Consider ADO & ADO.Net's old "General Network Error" as the best example of how not to do errors.  The key point here is the message should first say:
  1. what did not work correctly, and
  2. what you should do next to fix it
Stack traces etc should come later.
  • Appropriate.  Consider the audience of your application.  They are the audience for your erorrs too!  The level of detail I expect in an error from SQL Server is completely different to the kind error I expect from iTunes. 
  • Respect my attention span.  750 Event Log messages a day means I won't look at them.  Once a quater means I won't look at them.  The latter case should be emailed.  The former case probabbly should be replaced with one critical failure message :-)
  • Respect my privacy.  Passwords, maybe even user names, or anything that is sensative in the context of the application should not apear in an error message.  I don't have a convienient example of one with a password in it (maybe check a more complete source) but this would probabbly also extend to stack traces.
This is a growing list.  It gets revised when I see something done well, or something done poorly (or when I do something well, or when I do something poorly.  Now I've blogged it.

It started out with just the Informative rule, motivated by the cost of the support desk having to get involved in a support issue vs. the user working it out for themselves.

More formally, we could look at an error with the following criteria:
  • What does this message do for the user experience?
  • What does this message do to avoid the user having to call someone?


Wednesday, November 01, 2006 6:22:55 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [1]  | 
# Monday, October 30, 2006
Monday, October 30, 2006 10:17:15 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, October 18, 2006
So I've just worked it out...

If you want to edit a list in Datasheet View - an insanely useful feature - you must not have Office Basic or Office Small Business versions.

You have to have the Pro version of Office and make sure the "Microsoft Office List Datasheet Component" is installed in the "Office Tools\Windows SharePoint Services Support" option in selected as Installed under Office setup.


Wednesday, October 18, 2006 5:59:38 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, October 16, 2006
To the end of making my unit tests as easy to write as possible, I thought the default CodeRush template for adding a new NUNit Test Fixture to my projects could do with some tweeking, or at least customization.  Here's how I like mine:

<TestFixture> _
Public Class «Caret»«Field(ClassTests)»«BlockAnchor»
    
<Test> _
    Public Sub «Field(MethodTest)»()
        «Marker»
    End Sub
End Class

My next question is, how can I make the ClassTests field default to the name of the file?

After blog mint [?]:  There are extra fields that you can insert into the template expansion, these are Text Commands and String Providers.  You get to these by right-clicking the Expansion area and choosing Text Commands or String Providers and selecting from the list.  The FileName string provider might be just what I need.

Monday, October 16, 2006 9:30:34 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, October 13, 2006
I was sitting on the train this morning with my mate Robbie, we both had laptops out, both hacking a little bit of early-morning-commute-code.  Must have looked like a right pair of nerds :-)

Anyway, he was coding in IDL (no, not the IDL VC++ guys are use to...), no doubt doing some high science with DICOM data, and I was coding in VB.Net, so naturally the conversation drifted to languages!

I remarked that the bit I was working on was not an elegant example of VB.Net, but rather some hackage that works and will be cleaned up in a future rev.  I apologised for its lack if readability.

Rob remarked that, it was readable... but more like readable in the same way a novel is! 

Friday, October 13, 2006 11:35:49 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, September 29, 2006
I am so sorry about the title.  I am a child of a certain generation.

I deal a bit with XML in my day-to-day and "getting" XSLT was a pretty significant step forward in this for me.

Doug Tidwell's book XSLT was the key.

What prompted this revolation was seeing that XSLT was more than just a way of rendering XML to HTML in a browser, but that XML to XML translations can be exceedingly powerful.  Right now I am dealing with a data source that has been flattened from a normalized relational structure, and now it needs to be put back together into a third, different structure.  All this is do-able.

FWIW, my tool of choice currently for XSLT development is Architag's XRay... but I still prefer WMHelp's XML Pad for general day-to-day XML editing.

Friday, September 29, 2006 10:29:02 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, September 13, 2006
I thought I'd post an update from my path to continuous integration nirvana...

Today's installment is things I have learnt about writing unit tests.  Specifically I'm all about .Net and NUnit, but these are probabbly applicable in other scenarios too.

Name your unit tests correctly

What I mean to say is, name your tests as a verbose description of what the purpose of your test is. 

A good example:

<test()> _
Public Sub FooCanGenerateValidIDWhenInputValueIsNegative()

A bad example:

<test()> _
Public Sub FooSaveMethodWorks()

Can someone who dosen't code on your project (or better still, a non-coder) understand what the designed behaviour is for the Foo class from your NUnit results? 

But the most important reason is these tests must be granular and focused.  If you can't tell me what you are testing by the name of the test it is probabbly time to step back and look at the code you are testing.

Bug fixes should have a unit test

This is in two flavours:  Forwards and Backwards.

When I fix a bug, how do I know it is fixed?  How can I prove it is fixed?  Good bug reports are focused & granular.  Add steps to reproduce and now you are talking about a good bug report. 

It is also no mistake that the words focused and granular words are in this lesson too. 

Forwards:
By the time the tests are done they should describe the desired end result of the bug report.  Again there is no need to go all TDD unless you want to, but if the bug report is in the form:

An unhandled exception is thrown under some specified bad input data

then your test should show that no exception is thrown with taht bad input data.  Instant proof that the bug was fixed!

Backwards:
Looking at a closed bug report, how do I know what was done to fix the bug?
Looking at a broken build report because some unit tests failed, how do I know what bugs that code relates to so I can retest them?

The purpose of this lesson is to remove well it worked on my PC from the developers vocabulary.

Writing unit tests is a mind-space thing

While not going as far as TDD in my current projects (caution: there are TDD fanatics out there :-) the lesson I learnt from the TDD thing is when you are writing your tests you need to put yourself in the mindspace of the client of your code.  Forget for a minute how you implemented the method and express what you aimed to do in the method with your tests.

Confession alert:  At first I thought this was a bunch of bovine compost when I read it in the Agile/unit testing/TDD echo chamber.  Then, one day, when I wasn't paying much attention, I found a bug in my code through this method as I was writing it.  Clouds parted, a little beam of sun light came down and touched my head.  All became clear.  Lay your hands on the radio, children; for we have a new believer.

Tests should be easy to write

When writing heaps of tests agains the same class or library or whatever, write a base class that does the setup etc and descend your test class from this base class as a way of making the test method only contain as little code that is not the test as possible.  This can make it easier to bang out plenty of tests. 

Or if you want to use Code Rush or Snippites in VS2k5? 
Or if you want to do absolutely anything else to make it easier to bang out unit tests?
...just do it.  There is no wrong answer.

There is no need to make this harder on yourself than it has to be! :-)

Wednesday, September 13, 2006 8:29:01 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, September 01, 2006
Hows that for a long title? 

So there is a new version of Visual Studio (in CTP at time of writing) called Visual Studio Team Edition for Database Professionals - its aimed at people who might associate themselves with the title Database Professional.  I gotta say, it looks like a really good solution to some problems.

I attended a cabana session at Tech.Ed (Tech.James?) this year hosted by Greg Low on data generation in the product, and during the presentation it came up that it would be nice to have custom generator for Australian-specific data... so I thought I'd take a stab at it.

Below is a screencap of the kind of random data my generator will spit out.  Handy for columns where a check constraint may be forcing a given format for the data.  The format of the phone numbers is configurable by a property and the rows are conistant for a location so that if we generate a Vic address it will have a valid Vic phone number etc.



The good news is its really easy to do.  Even at this early stage the product has some pretty reasonable doco on what to do to write your own generators.

So my custom generator is available for download by clicking on this link

To install it on your copy of vsdbpro:
  1. Copy the DLL from that zip into the following path on your PC: 
    [Program Files]\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\
  2. Edit the config file at:
    [Program Files]\Microsoft Visual Studio 8\DBPro\Microsoft.VisualStudio.TeamSystem.Data.Extensions.xml with a suitable XML editor and add the following line:
    <type>deepdark.net.PersonalDetails, AustralianDetails, Version=1.0.0.0, Culture=neutral, PublicKeyToken=341d0bd35c6f7d28</type>
  3. Restart Visual Studio, you should see a new generator called Personal Details in the list.

The source code is hardly going to start a revolutiuon, but I can make it available if there is any interest - just let me know.
Friday, September 01, 2006 9:16:57 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
# Monday, August 28, 2006
This is a little creepy...

Just as Pluto gets demoted from being a planet, at work we decomission a server whose name is Pluto.

This alone means we should never use Earth as a machine name for a server.

Monday, August 28, 2006 9:54:32 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, August 15, 2006
So I've been battling against using the Solution task in NAnt to automate the build of a large VB.Net solution that includes heaps of libraries and a web service and all sorts :-)

I was hoping to have it done like this:

    <solution configuration="Debug"
              solutionfile="LargeProject.sln" >
      <webmap>
        <map url="http://localhost/Project/ProjectWebService/ProjectWS.vbproj"
             path="C:\Inetpub\wwwroot\Project\ProjectWebService\ProjectWS.vbproj"/>
      </webmap>
    </solution>


...but was getting lots of errors like:
error BC30002: Type 'Xml.XmlDocument' is not defined.

It turns out the source of this is all the odds and ends that VB.Net automatically includes in your project - I was only vaguely aware of them, and it seems like there is no option on the Solution task for it.

After some googling and general messing around, I added an Exec task to the build as thus:

     <exec program="C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.exe">
           <arg line="EPOnline2.0.sln /build Debug"/>
     </exec>


The down side is there is no nice output from devenv.exe like you get from the Solution & VBC tasks, but my build succeeds and that makes me happy :-)

After blog mint [?]:  I didn't read the devenv.exe /? help close enough!  If you include /Out at the end of the command line (i.e. after /build Debug in the above example) you do get the pretty output.
Tuesday, August 15, 2006 7:23:47 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 

This is more along the lines of the CI threads that have been occupying my thoughts of late.

I'm really impressed at the kind of technical documentation I can get from NDoc + the VBCommenter power toy, even more when it is generated and copied to my fileserver nightly as part of an NAnt script!

The next project for me on the NDoc front is to coax is to produce user documentation (rather than technical documentation) from the same sources with no extra work from me :-)

Has anyone done this before?  Is it another case of when you are holding a hammer everything looks like a nail?

Tuesday, August 15, 2006 11:24:27 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, August 02, 2006
There's not much to tell since my last (vague, sleep deprived, rambling) post on continuous integartion as a development technique in .NET...

But what I have found useful is using Draco and NAnt on a VB6 project!

The problem I was looking to solve is reporting in Microsoft Visual Source Safe.  Draco.NET supports VSS, so I made an NAnt build script with one target containing no tasks and I have Draco build it every night. 

The plus is Draco includes in its post-build email the details of what checkins have happened since the last build and by who... Instant daily check-in report emailed to your door :-)

Wednesday, August 02, 2006 1:15:33 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
I've alluded to this before - when all you have is a hammer everything looks like a nail.  I was thinking about XML then, but after chatting with an old mate the other day it became clear that it applies to Flash as well...

So a couple of profound rules: - I'm putting the Flash community on notice :-)

1. Don't play music.  I was already listening to something, thanks.  ...and I liked my music better.

2. If you absolutely must redesign the common UI metaphors like Buttons and Check-boxes they must work as well as the ones I am use to.  Dont make me have to 'Learn' how to use my computer again.

3. I'm not a mouse in a wheel and no I am not having fun following & clicking a beeping whatcha-mahoozit just to get what I came to the site for.  Yes, I came for a reason and yes that stuff is standing between me and what I want to see.  And No that dosen't mean you are not still very tallented at making beeping whatcha-mahoozits.

But on a more serious note, there are two issues still outstanding with the Flash community that can be an obstruction to less savvy users:  The Back button is useless and I can't bookmark where I am at.

So imagine I am training someone very new to computers about the web... it's going to go something like this:
yes, this is a web page... you can go Back (think bread-crums analogy) and you can save your spot (bookmarks in a book analogy)... oh except for this page - this is what we call a *Flash* page... no, not flash as in... oh forget it....

The point:  No one should have to care what technology the content is written in.  Not beginners and certainly not me.

What's the silver lining?  When the signal-to-noise ratio in any space takes an injection of background cosmic radiation the real cream of the crop just shines through.  Well implemented Flash is sublime.  The rest, well its just the rest.

Wednesday, August 02, 2006 9:56:37 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, August 01, 2006
I've decided to try the Visual Studio IDE enhancements from Developer Express after hearing some rave reviews.  One nice thing I noticed is that the installer detects the presance of VS2003 and VS2005 and installs into both IDEs if need be.  I like the philosophy of not having to buy the thing again whenever a new Visual Studio is released.

More specifically, these tools are Refactor! and CodeRush.

One way to describe CodeRush is as a template based code generator on a small scale.  It can insert comon language constructs with a shortcut key combination.  For example if you select a block of text and press t, the selection will be put inside a generic Try... Catch... Finally block.

First impression was that this thing was getting under my feet.  I know how line completion in Intellisense works and I like it.  In fact I preempt it.  Now things have changed aargh!  I might have to back-off the speed at which this kicks in, or maybe its a new trick for an old dog?

Refactor! is a different animal.  It provides Refactorings to your code inside the IDE with previews of the changes that look unreal.  All kinds of useful stuff like in one click you can extract an interface from a class's public definition.  Sweet!

Now all I have to do is learn to type properly, or just buy a better keyboard :-)

Tuesday, August 01, 2006 3:06:05 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
# Wednesday, July 19, 2006
I saw this post the other day on the IE team's blog while looking at some IE7 stuff...

I was unaware that the SV1 token gets added to your browser User Agent string after XP SP2.  I don't think in this case it matters if SP2 is more secure than RTM XP, I still don't want someone to know my patch level.  Call me paranoid...

As fortune would have it, fiddler has an answer!  Thanks :-)

Oh, with regard to IE7 - apart from all the user experience enhancements like tabs (thanks for coming to the party IE) etc the killer I reckon is in protected mode registry virtualization - I think we will see more of this in future!

Wednesday, July 19, 2006 4:31:03 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [3]  | 
# Thursday, July 13, 2006
So it's been a little while between updates on the blog, sorry about that!

I've been on a bit of an OS roller coaster ride of late.  I tried the latest LonghornI mean Vista beta (beta 2) on a couple of machines.  I didn't do a lot of homework because I have this bad habit with operating systems - I just grab the bootable disc and dive in the deep end.  I did this with Linux in '98 and it took me 6 years to kick the habit!  :-) 

The two machines were:
  1. Dell Inspiron 1100 laptop, P4 2Ghz, 1Gb RAM, integrated Intel graphics, 80Gb HDD
  2. Home-brew PC, P4 Dual Core 3Ghz, 2Gb RAM, 512Mb 6800 graphics, 1.2Tb storage
First thing's first - they both run fine.  The install was painless, the new features and UI are discoverable and I am well impressed with the direction Vista is taking. 

My problem is that the laptop needs to run Visual Studio 2003 to maintain some Web Services projects.  These require Front Page extentions on the local IIS to do debugging when I am on a train or otherwise not close to a server.  So after a week of new-OS glow and fighting uphill against IIS 7.0 (which does not and will not support FPE) I am presently formatting the HDD and putting XP SP2 back.  *sigh*

The desktop box runs a treat with the "Glass" enabled and all.  I am looking forward to running the final release on it. 

As an aside both these machines are running the Office 12 beta too!  They have taken things back to real core usability in this release and I think it's a very good thing.  There are some cool new features, sure- but the killer for me is in its usability improvements. 


After blog mint [?]:  I love Linux to bits and it has come along leaps and bounds in that time - I'm just a Windows guy at the moment.  2003 Server played a bit part in that.  I harbour no ill will to the penguin, it's just not me right now.  that's all.


Thursday, July 13, 2006 1:30:17 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [2]  | 
# Wednesday, June 28, 2006
Again, I'm sure that there is an easy resolution to this and I know I haven't read every page of the administrators guide, or every blog post, but this one is really getting to me.

Just say 2 development teams in the same company each have their own site, tracking issues for their own product.  The rules for the problem:

  • They would like to record the client who reported the issue against the issue.
  • We all work in the same company, and therefore we all have the same clients.  Each client may have a product from either team, or a products for both teams.
  • It is not apropriate for these issues lists to be in one site, because different partners work with different teams on different products.  These need to be kept seperate for reasons of commercial confidentality.
  • It must be scalable so that more teams can be brought online with minimal effort.
  • Custom development must be kept to a minimum.

I want to maintain one client list and one client list only that has views into each teams site.  I can't seem to make this work for me.




Wednesday, June 28, 2006 9:49:36 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [3]  | 
# Tuesday, June 27, 2006
Lately I've been receiving spam that seems to have no payload. 

No links to knock-off phallicpharmaceuticals.
No promise of promiscuous foreign brides
Nada!

They just have a dozen lines like:
oziuyebjrukdebrrpzewciungdjfapa 
So yes, they are successful in getting through my heuristic filters, but to what end?  What is in it for the spammer?

Tuesday, June 27, 2006 10:39:54 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [2]  | 

Here's my XML Hammer.  Useful for getting some XML into places where instinct might guide you to other choices.





Tuesday, June 27, 2006 8:41:50 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
# Monday, June 26, 2006

I'm new to Sharepoint, so here I'll start a list of Sharepoint Annoyances :)

#1:   It lets you think you are designing relational data... but you are not!

Some examples:

I have a list of clients, and I have a list of contacts (or individuals) at that client's site.  I am designing a form for entering job details and I want to link in to a job both the client who requested it and the contact at that site. 

I want the user to pick a client and then a contact that is valid for that site, but I can't seem to filter them!

Secondly, there is no validation!

I want to have a form where the user can enter a start date and a finish date.  No problems so far but logic dictates that the finish date cannot be before the start date!  I don't have a way of enforcing that.

I'm sure there are ways around these, but right now they are annoying!

Monday, June 26, 2006 4:55:31 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, June 24, 2006
I had mentioned model-view-presenter pattern in passing before, because after I saw it it struck me as a pattern that could be a really good solution to having the most decoupling between the UI and, well, everything below it.

The chance came  up to try it during the week on a small project so I gave it a go.

The View was a windows forms app.
The Model was a .NET Class Library with classes that roughly wrapped a set of SQL Server stored procs.
The Presenter was implemented as a .NET Class Library.  This library also contained the definition of the interface that the UI was to implement.

Some of the key advantages of this pattern:
  • The actual logic of the application is self-contained so it can be easily unit-tested.  Code that is easier to unit test is easier to get right.
  • The data layer is self contained and can be unit tested.
  • You can implement a couple of different data layers supporting different back-end data stores.
  • The only code in the UI is just to display the properties on the interface and raise events in the logic layer from the UI.
The key advantage I see for my kind of stuff is that as far as the Presenter is concerned, there is no UI past the interface that it implements.  It would be trivial to replace the Windows forms app with a ASP.Net app that implemented, or to have it feed a serviced componant over remoting, or....

Saturday, June 24, 2006 2:33:38 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, June 21, 2006
Is it that time again?  Seems like only... last year???

Oh well, I'm registered - see you at Tech.Ed 2006 in Sydney.



Thanks Frank, for confirming that there is too much to read on the Aussie tech blogosphere.

Wednesday, June 21, 2006 12:04:24 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, June 16, 2006

A week since my last blog post!  Here's a quick summary.

  • My head has been spinning at work.  Hit a busy period and I can't seem to work fast enough.
  • Sydney is starting to get C-O-L-D cold!
  • Gates is leaving Microsoft (later rather than sooner), Scoble is leaving Microsoft (I've been the web site for half an hour and I still don't know PodTech do)... would the last one to leave Redmond please turn out the lights? :)
  • The continuous integration thing is moving along.  Draco.Net, NAnt and NUnit all rock. 
    • Here's the trick for testing database code:  have your test setup put a transaction on the wire and have your test cleanup roll back the transaction.
    • I know I have only read the doc 8 times this week, but I think I'm starting to understand the DI pattern.
  • Microsoft renamed InfoCard to now be CardSpace.  WTF?  Still no cards?  Infocard is still a good idea - identity management is still very important but please guys drop the "cards" thing.  Not everyone follows WinFX developments up to the minute and you're starting to confuse people.  And I still don't have a satisfactory answer as to why we are doing this over protocols like HTTP and SMTP.  Why not another rev of these protocols to natively include identity, encryption and authentication, and then build identity management frameworks on top of them?
  • Neofiles has been doing my head in with talk of transhumanist singularities, cognitive liberty, liberation biology and nano-biotech.  For some reason I put my strongly skeptical BS-Filter on hold for this show and I am starting to think about these things.  I'm definately not sold on some of these topics.  Maybe I'm just short on sleep.

Friday, June 16, 2006 5:29:24 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, June 08, 2006
Been a while since the last security post, so while its a blogging day...

I was catching up on PaulDotCom security weekly podcast and during a discussion about insecure protocols like Telnet "behind the firewall" I learned that the RDP ("Terminal Services") is vulnerable to Man in the Middle (MITM) attacks.  In fact they put RDP into the same group as Telnet!

I remember when I started allowing RDP into my home network I did some research into if the encryption used by RDP is secure -which it is- but this vulnerability highlights that it is not enough and that it is exploitable by means of ARP Posion Routing to intercept your RDP session, including what you type at the login prompt.

So RDP is a bit of a fact of life for me at the moment, applying some defense in depth is in order.  Some layers we could add:
  1. Tunnel the RDP connection over SSH.  I really like this one because it adds a layer of authentication to the session, not just encryption.   This addresses the root cause of the problem:  So long as the encryption remains in place, RDP does not care how the traffic gets there.
  2. Tunnel the RDP connection over SSH.  Yeah, but this time it is to allow us to close port 3389, there by not advertising the availability of RDP on the host.
  3. IP FIltering & IPSec policy.  In my case I already have this in place for my off-site connections to only allow connections from know-good IP addresses.  This is equally valid for behind the firewall sessions.
  4. Certificates.  I'm a big fan of certificates as a factor to authentication.  I'll blog one day about using them to encrypt SQL Server's on-wire protocol.  Technet has a how-to that shows you how to set this up with Windows 2003 Server SP1 & Windows XP.

Thursday, June 08, 2006 11:37:50 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
...well, maybe not.  :)

More accurately I love a good keyboard and all the keyboards I want I can't afford.

At home I use the Logitech S 510 cordless desktop + media remote.  At AUD$179 it is a serious commitment to your desktop but I spend more than a healthy amount of my waking hours at a PC of one kind or the next so it is worth making it comfortable.  In summary I can't recomend this keyboard highly enough.

At the other end of the scale is the Dell SK-8115 that came with my new hugely expensive powerhouse PC here at work.  Some people like them but they are cheap and flimsy and move when you type.  Also the little legs that raise it up keep flipping down on me.  Dell, if we spend $5K on a PC, please don't send me a $20 keyboard!

Here's a list of what's hot in keyboards:

Leader in the "Great concept" category is the Data Hands but at USD$500 - just no.

Along the same path and a little closer to earth is the Frog Pad.  It's based on the concept that the
the highest-frequency occurring keys are easiest to strike.  The next least used 15 keys are "under" the first with one shift. The rest are both shifts under the first.  Starting at USD$130 they are closer to reality.

Alpha Grip AG5 looks like a gaming controller but are actually a QWERTY layout keyboard with a trackball.  I worry that I'd blow my $USD99 for one and then not be able to retrain my fragile brain to use it!

Now, this is the absolute king:  The Optimus.  Not available until the end of '06.  Note that each key is a software-controlled OLED that has customizable pictures.

Thursday, June 08, 2006 1:00:17 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [2]  | 
# Thursday, June 01, 2006
I've setup a Continuous Integration server called Draco.Net on my desktop box (for the moment) here at work.  Setup was really easy after one minor hitch that I would have worked out eventually :)

---------------------- Done ----------------------
Build: 9 succeeded, 0 failed, 1 skipped

So what's next? Setting up NAnt for building, unit testing with NUnit and looks like you can add FxCop analysis to the build too.  Yay.  Oh, and also getting an rss feed out of Draco would be nice!

Is all this worth it?  Time will tell.

Thursday, June 01, 2006 9:44:41 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, May 30, 2006

William Bartholomew posted a trick to the [ausDotNet] mailing list this arvo about when you need to know what is going on with an MSI installer, specifically the kind that come wrapped in a .exe bootstrapper.  It was in response to troubles Dr. Pete was having with the (acquired) Microsoft Office Groove 2007 Beta client...

See if you can extract the MSI packagr from the installer, usually OG-EN.exe /x c:\temp\
Then, you can use msiexec /i c:\temp\msifilename.msi /v* c:\temp\install.log
Then, open up install.log and see what it's complaining about.
Tuesday, May 30, 2006 5:39:23 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, May 29, 2006
In my current development box at work I am blessed with a pretty nice dual-head video card.  Off it I run my vintage Gateway VX900 19" CRT plus a shiny new Dell 1704FPT LCD.  The LCD lives on DVI and the CRT lives on 15-pin VGA dsub.  All pretty normal.

A few weeks ago I decided to try rotating the LCD into the vertical orientation and I have to say I'm hooked. 

What I like most about it is some windows like browsers, Acrobat, Word look better vertical however some windows are more useful horizontal, like Outlook, Visual Studio etc - this way I can keep both. 
 
I am convinced that there is less eyestrain reading documents in the vertical orientation much like we do with hard copy because the eye has a shorter distance to scan left to right.

Now my desktop is thus:





To be fair, some things suck about it:
  • Some apps just don't know what to do, and pop-up a window too tall on the horizontal window or too wide on the vertical window.
  • My CRT can do higher resolutions than 1280x1024, but it feels goofy dragging windows between screens and having them shrink and grow.  Freaks me out :)
If you have a vid card + driver that supports it, plus the right hardware I say try it out.  You might like it :)

Monday, May 29, 2006 1:10:42 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, May 23, 2006
I just got this message from Skype about a security update:



Apart from the stray non-printable control char after the question mark, this is pretty much the way security update notices should go out for consumer applications.

The security fix only works if people download and run the update, and if the message can't be read by the intended audience because it is deep in techno-babble your patch is all for zip.

It reminds me of way-back-when comparing iptables on Linux 2.4 vs. IPF in OpenBSD 2.x.  The one factor that made OpenBSD more secure for me in this case was the rules were written in words the config file rather than as parameters to iptables making them less error prone and hence more secure.  I believe both those tools are now left to history now anyway...

Anyway, well done Skype :-)

(NB:  They also blog :-)

Tuesday, May 23, 2006 6:19:12 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, May 17, 2006
The UI has had a bit of a make over.  It renders well in Firefox (watch the vids!)

While giving flickr a congratulatory aimless surf and tagging some of my own recent photos, I came across some exceedingly cool graffiti and also this bit of chalk graffiti from the streets of London.  I'm a big fan of stencil graffiti and there is just too much cool stencil and chalk work on flickr.  Go on, you have to check this out!

One thing I like most about flickr however is that the Yahoo! juice is just subtly in the background.  I'm not a big fan of Yahoo!  I don't hate them, I just never learned to love them.  To me now, flickr is 0%-suck.  If the Yahoo! banner was in your face all the time it would never be able to not suck at least a little.  MSN/Hotmail/Live - Are you listening?

On the topic of graffiti, I'm not a fan of tagging.  Nothing too deep, just that for the most part it's ugly.  It was interesting to see that Marc Ecko's tagging of Air Force One turned out to be a hoax.  Had to be really and I don't think anyone actually thought he did it, but the concept rings true.

Wednesday, May 17, 2006 9:06:29 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, May 12, 2006

Even embracing its manifold faults, I'm still a fan of Microsoft Exchange server.  It has been a tempestuous relationship of the years but I'm still there. 

However I have recently had cause to look at MailEnable and I have to say I am very impressed. The web mail is better than I expected and I think it's a keeper.  There are still a couple of configuration items I need to get straight but initial impressions are good.
Friday, May 12, 2006 9:20:17 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, May 09, 2006

Something more we can all do:  Sender Policy Framework.

http://www.openspf.org/index.html

also

http://www.ietf.org/rfc/rfc4408.txt


The gist of it is the SPF record in the DNS identifies all the valid hosts that are allowed to send mail for that domain.  Mail should not be accepted for domains with an SPF record if the originating host is not in the SPF record.

Anything that reduces spam gets my vote!

You can check your domain for this and related details at DNS Report.

Tuesday, May 09, 2006 5:22:11 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, May 08, 2006
I posted before about trying to determine if a SQL Server trigger is enabled or disabled.

The answer came via SQLJunkies and of course comes to us by way of OBJECTPROPERTY function.  The property is: ExecIsTriggerDisabled.

I learnt all this back in the SQL 7.0 days and my fav trick is to dive into the sysobjects & syscolumns tables for all kinds of metadata.  I never caught the OBJECTPROPERTY and the Information Schema views. 

My homework is to now get busy learning the OBJECTPROPERTY function so I can keep up with being 1 version behind :-(

Monday, May 08, 2006 11:50:31 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
Richard and his guest Kent Alstad of MCW Tech talked on ep174 of DNR about their new venture Strange Loop.

While details are scarce what we are talking about is a hardware appliance that implement managing state and compression in a router.  This means the ASP.Net View State is managed by the appliance.  The way this need to be seen is in light of the problem of scaling a web app from one server where inproc state management is OK to a multi-server web app where a SQL Server is used to hold the state in order to avoid problems arising from afinity: subsequent page requests need not hit the same server but that implies a trip to the SQL Server for each page view.

What Strangeloop are promising is the scalability of using SQL Server session state with the performance of Inproc state.  Oh so cool.

So the question I have is:  Where's my SQL Server appliances?  Great example is protocol encryption for SQL Server.  It's obscure and far from intuitive.  TDF is understood, as is SSL.  Someone give me a sexy 1U rack gizmo that glows blue and makes it all happen :)

Monday, May 08, 2006 11:23:11 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, April 28, 2006


I was listening to DNR last night, the guest was Kim Cameron and they were talking all about Identity.  The topic of the let me get my work done button came up.  This is the digital version of the boy who cried wolf story. 

When the user is bombarded with endless security dialogues that they don't understand they blur into one big let me get my work done button.

I thought I'd represent it graphically :)


Friday, April 28, 2006 9:51:32 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  |  20060428-What-Non-technical-users-see.jpg (64.61 KB)
# Thursday, April 27, 2006

When you think you have found all the places to set exchange server's data stores and moved them to a data disc you should re-check! 

There is always one that is still set to log to your system drive and the gods of pain and irony will find a way to fill it.

...with apologies to the hundred of thousdands of people trying to read this blog between midnight and 10:00am...
Thursday, April 27, 2006 10:04:58 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, April 26, 2006

So I mentioned earlier that I am excited about using XPath against XML data stored in SQL Server (v2000 at the moment) but I keep coming up against the same problems, like text/ntext data types are invalid for local variables in a batch and I can't fit the documents I want inside varchar(8000). 

The result with the most Google Juice on this points to the solution we all want.  There needs to be a version of sp_xml_preparedocument that accepts a pointer to a text/ntext column.  There are various solutions around, none of which are kind on server resources (like creating an undetermined number of varchar(8000) variables in scope) and none of which are pretty.

The chances of getting this went from slim to none last Nov.  Oh well.  I've yet to sink my teeth into SQL Server 2005 and I know they have done a lot with XML in that release, but Microsoft:  Do you think every system and team cuts over to the new version of your products the day after launch?  I understand you're excited but the same happened to VB6 when VS.NET 1.0 came out.

The project I have in mind involves taking the XML out of Excel documents and working with it using XPath and XSLT.  So for now this dosen't live in the data tier.  Oh well.  The sun will rise on the morning.

Oh and a nod to the brainy and beautiful Anina for "google juice" links. 


Wednesday, April 26, 2006 9:41:25 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [2]  | 
# Wednesday, April 19, 2006

Since I was doing nothing else on Monday, after the blog post below I spent a couple of hours going through the work in Visual Studio.

While I am still not sold on the concept of the tests driving the development process, it does make you consider your class design from the point of view of it's consumers.  Also the screencast did help bring some clarity to practical test design with NUnit, which is something I strugled with earlier.

My next problem with it:  How do we manage the problem that arises from programmers testing their own input validation for example?

Also the MVP pattern was easier to implement than it looked on DNR TV.  I look forward to watching the episode dedicated to it.
Wednesday, April 19, 2006 9:00:07 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, April 18, 2006

Maybe it's a hangover from a public holiday but I can't seem to find out from the system tables or sprocs.  Man it can't be that hard!

Google here I come :-(

Stay tuned for update if I find out...
Tuesday, April 18, 2006 9:30:21 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, April 17, 2006

So I'm catching up on some DNR TV with an easter egg and I'm watching the episode on Test Driven Development with Jean Paul Boodhoo [part 1 & part 2].  The obvious flaw -which they caughed to later- was trying to cover TDD, Interface-based programming with mock objects using NMock, and the model-view-presenter pattern, and an intro to ReSharper in one show.  Just too much new information.  Later they did a show on MVP (I am still to watch this...)

Anyway, it's clear the JPB is very capable at making this agile + patterns mashup work well for him, but I can't escape the common criticsm that it's just so much heavy lifting up front!   I'm prepared to accept that this work pays dividends, but they must accept that at first look this methodology looks to be the enemy of prodictivity, and that is going to be a very hard sell for regular mortals in the SME/ISV space.

The one idea I'd like to contribute to the debate is a what-if:  What if JPB & his freaky kind are just doing in long-hand now, what in future revs of Visual Studio we will be able to declaratively to get the same benefit with less effort?  Then, I'd be interested!

While on the topic of DNR, and DNR TV, the Dot Net Rocks! guys (I get the impression Carl specifically) have been on the bandwagon of using BitTorrent.  Makes sense when you are distributing content like they are.  They like µTorrent, me I hvae been a fan of Shareaza, because it's an open-source project rather than a commercial veture it has no problems being banner & pop-up free and has a seriously slick UI, but I just found out uTorrent supports RSS feeds that include .torrent files - perfect for having your DNR and DNR TV downloaded!

While on the topic of Carl, Pwop Productions, and their shows... Hanselminutes show #12 "Top Ten Utilities you Didn't Know You Had" is well worth 30 of your minutes.  Some old, some new, there has to be a time-saver in this bunch for anyone.

Obviously it's been too long between blogs for meso apologies for the link-fest and drifting between tangents... you may return to you're regular scheduled programming...

Monday, April 17, 2006 1:11:52 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [2]  | 
# Friday, March 03, 2006

Another thing I am seeing more of that requires some comment is poor requirements definition and specs for technical work.

An obvious benefit of a development team working to correct and complete specs is the output can be measured against the spec to give the project a logical and objective conclusion.

The other side of this is a healthy spec & requirements sesssion incourages the stakeholders in the project to actually think through their requirements.  Lesson: Don't take this for granted.

I've just seen a couple of notable examples of this lately when questioning a minor point in the spec has had the client say "Ah!  I didn't think about that!" raising more fundamental questions about the project.

I'm working on a throey that you can never ask the average guy what they want, because by virtue of being in the middle of their own business domain they are blinded to actually knowning the right answer.  You can only learn what they need.

After blog mint [?]:  Just more on that "ah!" moment.  I'm not saying it's a failing on the stakeholder's part.  It's natural and healthy part of requirements definition.  Just don't forget that it can (and will) happen.
Friday, March 03, 2006 10:38:08 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 

I know what makes me sick and what makes me well, but that dosen't make me a doctor.

Knowledge of a specific business domain dosen't qualify you through some holy invocation to be a database designer.

Sounds like I'm taking a pretty hard line on this :)

Really it all stems from seeing people put in way too much effort to cope with bad ideas.  Take for example this pretty simple rule of normalization:
  • Every time a row and column meet, that cell should hold one and only one bit of data.
Break that rule and you will be forever doomed to write hard to maintain queries.  I was just discussing a scenario that needed to  regularly update part of a field for a large number of rows.  Luckily that scenario isn't seeing the light of day <phew>

So, what criteria do you think should be on the test that issues licenses to develop databases?
Friday, March 03, 2006 10:01:55 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, February 28, 2006

Some possible reasons:

  • VCs didn't learn from the first .com crash
  • Technology pundits didn't learn from the first .com crash
  • flick
Yeah, let the VCs and technology writers (with the exception of Robert Scoble) race each other to the bottom of the ocean.  Long live flickr!

Why I reckon flickr rocks:
  • They blog.
  • They know about Interestingness.
  • You can get practically everything delivered over RSS.
  • Tagging just rocks.
  • You can upload straight from your Windows folders, or by email, or from OSX, or from iPhoto, or...
  • The user experience is very nice.  Good implementation of AJAX.  Very clean UI.  Branding is nicely done.
So yeah, hype will always be there but if it was all for flickr, well, it wasn't wasted :-)

(go on, give my flickr page a nudge...)
Tuesday, February 28, 2006 9:51:50 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [2]  | 
# Tuesday, February 21, 2006

OK, this is my wishlist for a proximity security device for the Windows platform.  There are a couple out there, but none that do all what I want, and are available locally and are affordable.  Maybe no more than $100-150 initially and comming down with volume.

Backgrounder:  A proximity security device is just a gizmo that is aware of how close you are to your computer, and secures it when you're not around.

  • It has to work with Windows integrated security.  This means not starting a new process that covers the screen and requires yet another local password store.  Nor somthing that starts the Windows screensaver.  It has to lock Windows at the NT Security later.  It should also be Group Policy aware, so your AD could stop your account being used on a machine that did not support the device.
  • You're going to need a dongle on your keyring, and some receiver in your pocket, but No USB!  The system should not be able to be neutralized by ripping out the dongle while you're away from your desk.  Also USB leaves too much of the process visible to the driver stack.
  • It needs to be tamper evident.  So if a machine is rebooted while secured it needs to be noted somewhere in big red letters!
  • It needs to pause Windows Media Player/Winamp/Sonique/iTunes :)
  • You must only be able to log in to the machine again when the dongle is in proximity.
  • Maybe even some biometric on the keychain dongle so that it can only send back a signal when your fingerprint matches.
  • It would be nice if one keychain could lock multiple machines.
  • Lastly, and most importantly, it must automatically lock your machine when you move a certain distance from the machine with no questions asked.

Has anyone seen such a gizmo?  Or am I meant to keep dreaming :)
Tuesday, February 21, 2006 2:03:43 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [1]  | 
# Monday, February 20, 2006

OK, here's my monthly props for CryptoGram...

Bruce Schneier links to a story where some Russians use a 'dead drop' technique via anonymous email systems like Hotmail.

The idea is that 2 or more people share an email account and instead of sending email messages to each other they just save their message as a draft email for the next guy to read. 

I like this as a specific case to illustrate the more general point about security based on "building higher walls" being bad becuase it assumes that all entry points are known!

After blog mint [?]: I've been thinking more about this... the key isn't that the message never went across the wire because it did (from the PC to the Hotmail server) but it's that it didn't leave Hotmail via SMTP, so the goal in sight is to avoid SMTP message detection and signal analysis based on SMTP traffic.  Taking that as the general case leaves open a bunch of other scenarios, like storing secret data on mobile SIM cards for example.  Just a thought...
Monday, February 20, 2006 4:56:46 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, February 16, 2006

This last couple of weeks I've been really getting into XPath, and SQL Server's sp_xml_preparedocument and OPENXML() syntax. 

I keep finding cool things to do with it but I can't see a way around the problem of sp_xml_preparedocument accepts only a local variable as the source document, which limits your document size to VARCHAR(8000) size -or half that for NVARCHAR.  I have not seen that limit yet in my work, but it still seems a little low.  What about ntext guys?

I'm gonna have some real-world XPath coming soon, this is just a pre-post warning :)

Thursday, February 16, 2006 12:17:33 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, February 02, 2006
Great link from Jules: http://www.pbs.org/cringely/pulpit/pulpit20051117.html

If this is the future of the internet, count me in.

Thursday, February 02, 2006 10:13:34 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, February 01, 2006
There is a new breed of imaging apps that have come up, at the moment I'm thinking of Adobe Lightroom (mac only, currently beta) and Apple Aperture (mac only, v1.0 and could use some polish).  The good thing is they are rethinking the UI for the specific tasks at hand.

But the old stalwart in this space is Photoshop (currently in 9th revision a.k.a "CS2").  So why does the world need both?

I think it comes down to the UI paradigm. 

One of the strengths of Photoshop has always been that it presents the user with a toolbox.  There isn't a button to make embossed text for example, however useful it might be.  The UI design expects you to know how to combine selections, masks and blend modes to create an embossed look for you text. 

This is a benefit not a limitation because PS is a creative application - your text bares the look of your experience and technique and matches the rest of the image perfectly.  If you want you can then record an action to make your own embossed text button.  Next to this, a generic embossed text button would give very average results.

The downside however is it requires considerable understanding of all the tools at hand to get the best results.

Compare to that the UI, or more the user experience, of Lightroom and Aperture.  These are focused on the needs of specifically digital photographers using high-end cameras (even one of these or these!) and pro workflow.  Because the UI is so focused they are able to encapsulate things that use to be a dozen clicks in Photoshop & Adobe Bridge & Adobe Camer RAW into one slick UI.  This is also a good thing.

So to examine the general case what does this tell us about UI design and user experience that can be applied to the applications we write?  I think it just underscores the need to directly address the outcomes the user is working towards in the UI, rather than having the UI just as a way for the user to interact with your program logic.

So look at your apps and ask... which UI are you; the toolbox or task-focused? 

Wednesday, February 01, 2006 1:17:33 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, January 12, 2006

Tracking stray connections using profilerTimes when this can come into play is in multithreaded apps, or apps where you may be supporting simultanious users like in an ASP.NET application. 

 

Generally any time you are asking resources from the server it should be using the Try... Catch... Finally pattern for allocating server resources and releasing them as soon as you know you can do without them.  (Nod to Andy Rich on Deterministic Finalization)


One thing that is going to help with this however is to set the appname in your connection string (Application Name={1};) for filtering the Profiler results.


So here is a Profiler trace useful for keeping an eye logins, logouts and stored procs executed inbetween:


Download: deepdark.net_Connection_Monitor_20060112.zip

Thursday, January 12, 2006 12:45:32 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [1]  | 

Something I have been giving thought to is that the .NET Framework exposes perfmon counters for all manner of useful stats. 

 

An unlikely tool?  Not so much... Of particular use is the feature where perfmon can track exceptions thrown throughout all managed apps or, alternatively for any chosen running managed application.  You can then compare the number of Finally blocks hit after an exception was reached (there is a counter specifically for this!) vs. exceptions thrown.  In normal conditions I don't think I'd like these todiffer significantly.

 

Really this is using perfmon to track stats from .NET apps provided by the framework; but performance isn't far from the surface.  Throwing and Catching exceptions is a very costly operation for the Framework and is a significant performance hit to a running application.

 

Three things, and some links: 

 

1. You don't have to be looking at your dev machine.  If you have administrative access to a test server you can remotely watch any perfmon counters.  Useful if your application runs as a service or for ASP.NET applications. 


Also, create a shortcut to perfmon.exe in your System32 directory to get to quick access to the Run As... command for those running their developer environment with least privilege (nod on this to Don Kiely, Michael Howard).

 

2. If you need to track these in a running app like a Windows Service or a ASP.NET application consider using MRTG to graph

the results for you.  I've used this before as a make-shift NMS console monitoring server system health. It's more secure than SNMP and very low on resource use.

The official MRTG site has the basics for setting up MRTG on Windows, but Castellan has a (slightly dated) but much more relevant guide.

 

3. Consider logman to configure the Performance Monitor service.  Again this is worth a blog post by itself.  Open a command prompt and logman /? for more


 

Where to next?  One day I'd like to automate perfmon logging as part of an NUnit test harness to give another measure of quality parallel to Nunit.  I'll keep you posted.

Thursday, January 12, 2006 12:08:31 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, November 11, 2005

Quick post today about my favourite SQL Server “feature”.  This is when you create a user account the default database is master.

The only sensible reason for installing the Northwind database I think is so that you can set it to be the default database for logins!  :-)

I wonder how many times in history people have just opened the Query Analyser and ran a script accidentally against master rather than the database they intended. 

(Humph!  What ever that number is... add one to it)

Friday, November 11, 2005 3:58:34 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, November 07, 2005

It's been a little while between posts, so I thought I'd share a tip about using Fiddler to debug .NET SOAP Web Service Clients.

Once you install Fiddler it sets itself up as a proxy on port 8888.  You then use the Fiddler UI to inspect sessions made from your application to the IIS hosting the web service.  Fiddler lets you inspect the raw HTTP traffic that is exchanged in a SOAP call, and you can even modify an old session and resubmit it with modified data!  Great for debugging.

Below is a sample (VB.Net 2003) adapted for readability from an actual project I'm working on.  The point of the sample is setting Proxy property of the web service reference to a WebProxy object.


Dim
NewUser As RemoteWebHost.User
Dim UserServices As RemoteWebHost.DatabaseSync

' Adding this line lets Fiddler track the HTTP Sessions.
UserServices.Proxy = New WebProxy("http://127.0.0.1/", 8888)

With NewUser
   .UserName = "fred"
   ' [...]
End With

Try
   UserServices.UserAdd(NewUser, Nothing)

Catch ex As SoapHeaderException
   ' [...]

Catch ex As SoapException
   ' [...]

Catch ex As Exception
   ' [...]

End Try


Monday, November 07, 2005 11:56:31 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, October 06, 2005

Looks like it's about time for another post!

This one is about the SQL Server system tables.  These are a fav of mine because I find them so useful in scripts. 

The caveats when dealing with them are you need to be mindful of SQL Server versions.  Everything that worked on SQL Server 7.0 will work on SQL Server 2000, but there are some minor tweaks in SQL Server 2000 that are not valid in SQL Server 7.0.  Now is not a good time to mention SQL Server <= v6.5 because the system tables had an overhaul for 7.0, and I haven't checked any of this code on Yukkon/SQL Server 2005 yet.

My fav thing to use the tables for is dealing with object existance in scripts.  In my books a good T-SQL script can be run over and over without damaging the database.  Put another way, if your SQL Script throws an error if it is run twice against the same database it's not a good T-SQL script.

Consider we are dealing with the following table:

CREATE TABLE testing_data (
    pkey INT IDENTITY (1,1) NOT NULL,
    created DATETIME DEFAULT getdate() NOT NULL,
    modified DATETIME NULL,
    deleted BIT DEFAULT 0 NOT NULL,
    testing_val_1 NVARCHAR(15) NOT NULL,
    testing_val_2 NVARCHAR(255)
)


For whatever reason we want to drop and recreate this table each run, you could put the following statement before it:

IF Exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[testing_data]')
    AND OBJECTPROPERTY(id, N'IsUserTable') = 1)
    DROP TABLE testing_data
GO

This is the syntax you will see if you choose to include Drops in scripts you generate from the Enterprise Manager, but I don't use it much, mainly because I can never remember the OBJECTPROPERTY() syntax!

Typically I do the following:

IF Exists(SELECT [id] FROM sysobjects
    WHERE sysobjects.[name] = N'testing_data'
    AND sysobjects.[type] = N'U')
    DROP TABLE testing_data
GO

I feel that Microsoft are hinting us towards using OBJECTPROPERTY() for future version compatability, but I still favor this syntax because apart from being easy to remember it's easy to adapt for other kinds of objects, e.g:

IF Exists(SELECT [id] FROM sysobjects
        WHERE sysobjects.[name] = 'prGetTestingDataRows'
        AND sysobjects.[type] = 'P')
    DROP PROC prGetTestingDataRows
GO

So if the Type column in sysobjects is 'U' for user tables, and 'P' for procedures then there are no prizes for guessing what TR, D & V might mean.

For a more complex example, lets say you want to change the type of the fileds testing_val_1 to NVARCHAR(35) ONLY if it has not been changed before, you could wrap the ALTER TABLE stateement in the following BEGIN... END:

IF Exists(SELECT syscolumns.[name]
    FROM syscolumns
    LEFT JOIN sysobjects
        ON syscolumns.[id] = sysobjects.[id]
    LEFT JOIN systypes
        ON syscolumns.[xtype] = systypes.[xtype]
    WHERE syscolumns.[name] = 'testing_val_1'
    AND systypes.[name] = 'nvarchar'
    AND sysobjects.[name] = 'testing_data')
BEGIN
    ALTER TABLE -- ... Implementation ommited for clarity
END

So having only touched two or three sys tables we have a couple of good tools that are easy to use.  I'll cover more at a later date, in the mean time enjoy the extra metadata!

After blog mint [?]:

Here's an actual practical example from a script I have been working  on recently (user name changed).  This script makes a dozen or so procs, the svcapp account is a login used by a service that only has rights to exec these procs, and no rights granted to the base tables.  This automates granting access to the created procs, and it much quicker than doing it in the SQL EM:

PRINT 'PART 4 - Granting access to user account'
GO

DECLARE @sql NVARCHAR(512)
DECLARE @name NVARCHAR(128)
DECLARE @usernm NVARCHAR(128)
DECLARE cr CURSOR FOR
    SELECT [name] FROM sysobjects
    WHERE type='P'
    ORDER BY [name]

SET @usernm = 'svcapp'

OPEN cr
FETCH NEXT FROM cr INTO @name

WHILE @@fetch_status = 0
BEGIN
    SET @sql = 'grant exec on ' + @name + ' to ' + @usernm
    EXEC sp_executesql @sql
    PRINT 'Granting EXEC on ' + @name + ' to user: '
    FETCH NEXT FROM cr INTO @name
END

CLOSE cr
DEALLOCATE cr

PRINT 'Done.'
GO


Thursday, October 06, 2005 11:24:38 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
# Wednesday, September 21, 2005

I was just thinking, it's about time I talked about SQL Server on my blog LOL

Here are 5 tips for creating well designed tables in Microsoft SQL Server.  They are in no particular order and it's far from an exhaustive list, but it makes for a good standard I think.

1.  Keep your tables narrow:  I don't just mean about the number of columns per-table, but also the width of those columns.  Normalization is your friend here.  I won't go into it here yet, but shoot for 3nf by default. 

By keeping an eye on table width and keeping your rows as narrow as you can you will get more rows on a page which will help you in case a query misses and index and requires a table scan.


2.  Add a deleted bit column to your tables.  Design your tables with an extra column called "deleted" or something like that.  Instead of removing the row from the table if there is a delete, set this flag = True. 

Some reasons you should do this are:

  • It opens up more options for implementing an undelete function and it helps archiving/unarchiving old data.
  • It's non-destructive!
  • It helps index fragmentation.

 

3.  Maintain aggregate tables.  This one probabbly applies more to transactional system than others but by using maybe triggers or a scheduled job to maintain seperate tables that store common aggregates for your main tables you will for make your reports more efficient and can simplify queries and joins. 

Two things to remember: 

  • These tables may not be indexed the same as the transactional tables, but this is a good thing.  Choose your indexes on these tables to suit exactly the queries you need.
  • If you require the aggregate tables to be absolutely up-to-date with the main data tables then using triggers may be the best solution but don't over do it!  Triggers can be costly and have an adverse effect on transaction log throughput.

4.  Maintain created and modified timestamps on each row.  Design your tables with columns called created and deleted and store the timestamp of when the row was created and also the last time the row was modified.  Do this as well as an audit trail. 

This is the kind of gift that just keeps giving!  Some examples:

  • Once your little back room app has 'grown up' and now needs to feed the data warehouse?  No problems! 
  • Need to validate your aduit log or a point-in-time restore?  No problems.
  • Users always love to see these details on the screen, or give your app a history feature like a web browser has so users can backtrack to what they were doing before the phone rang?  No problems.

5.  Don’t allow null unless it actually valid.  Don't be scared of Null values, but only allow them where they make sense.  Remember Null doesn’t equal "" or 0 - it means undefined. 

Consider the mod timestamp (from point 4 above) on a newly created row.  It has never been modified so Null actually makes sense.  The worst thing to do to these kinds of fields is to use "magic" values to avoid null columns,  for example giving "01/01/1970" the special meaning of "unknown" is just a waste of effort and makes your database usable only by applications that know these specific facts, seriously harming interoperability.  Also consider a table that joins to itself to represent a hierarchy - null can be valid in the parent field.

That said, don't allow nulls anywhere that they don't make sense.  If you find yourself thinking about optional fields consider normalizing, or using an attribute-collection pattern instead!   The thing to avoid is creating tables that has a column for each of the potential fields.  The typical example is having one field for each of business phone, business direct line/ext, home phone, mobile phone, fax number - each of them  with the same validation rules, and most of the rows  don't fill all columns!

So there you go!  5 steps closer to peace in the database world!

Wednesday, September 21, 2005 3:58:44 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 

Jesper Johansson has a good post on his blog this morning about what to do with the Built-In Adminstrator account.
I think this quote could become a new mantra: The built-in Administrator is basically a setup and disaster recovery account. Hallelujah!

Wednesday, September 21, 2005 10:23:36 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, September 15, 2005

I thought it time to recap some old database theory ahead of SQL Sevrer 2005 and the potential pain that CLR integration may bring to the DBA/Developer relationship.

Like all technology, if it's not used correctly it's just plain dumb.  CLR integration has been discussed between gurus whose shoes I am noth worth to clean ad nauseum, so we won't cover it here.  In a nutshell we are talking here about the integration of the Microsoft .NET Framework and runtime into Microsoft SQL Server.  This will allow you to write managed code in the database and a bunch of other cool things.

The thing to be mindful I think is when dealing with a .NET complex type.  Consider you're dealing with point data (i.e. x,y,z coordinates in space).  How would you represent this in relational data?  It may be convienient to store each point as some kind of string (NCHAR(5) in SQL Server types maybe) but that's just poor normalization.  What then happens if you want to process all the y values?

More correct may be three integer or float columns - one each for x, y and z.  This is getting there but what could be a scalar result from this?  It would have to be a concatination like:

SELECT cast([x] AS VARCHAR(3)) + ',' + cast([y] AS VARCHAR(3)) + ',' + cast([z] AS VARCHAR(3)) AS Point

to get

Point      
-----------
4,20,9

(1 row(s) affected)

...And that's ugly :)

So what's the bottom line here?  One of the most exciting things I am looking forward to in SQL 2005 CLR code is the idea of using a managed custom class to describe a point, and having it as a scalar result in a T-SQL operation.  That's hot if you ask me!

So what could be the problem?  Some peanut somewhere is probabbly going to use the new found CLR powers and code up a Tetris implementation and have it loaded into the CLR inside SQL 2005.  Sure you could do it, but all you are going to do is anger some DBA and give a bad name to CLR code, making it harder to adopt the correct implementations out in the field.

I'd love to give some credit where it is due for this post, but I can't remember whose writing it was that got me started thinking about this.  Whoever you are, thanks!

Thursday, September 15, 2005 1:20:07 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, September 06, 2005

Ok, so part of this post is a plug for Greg Low's podcast, SQL Down Under -  just to get the caveats out of the way first! 

The guest in this week's show is Itzik Ben-Gan talking about the T-SQL language that is native to Microsoft SQL Server.  About 11 minutes in, his discusses how any problem you can face in T-SQL (or coding in general I'd suppose) is really a logic problem.

The example he gave (that I have illustrated below in a sample) is of the problem of counting the number of occurances of one string in another.  Instinctively, we sometimes start looking at a itterative process, to count each occurance as it occurs.

He proposes a deceptively simple solution:  Replace every occurance of the string being searched
for (@needle) with a zero-length string. 

You can then compare the length of the original text  (@haystack) with the modified text (@delta) and divide that by the length of the string being searched for (@needle) to reach the number of occurances of @needle in @haystack.

Again, the logic of this solution is Itzic's not mine :)

Here's a simple implementation of this logic that illustrates the point well, and ends up a much cleaner (and possibly faster) solution than the itterative one.

---------------------------------------------------------------------------

DECLARE @needle CHAR(4)
DECLARE @haystack CHAR(255)
DECLARE @delta CHAR(255)

SET @needle = 'pie'
SET @haystack = 'meat pie, shepherds pie, pork pie, mud pie, ' +
            'cutie pie, mushroom and beef pie, meat pie, ' +
            'shepherds pie, pork pie, mud pie, cutie pie, ' +
            'mushroom and beef pie, meat pie, shepherds pie, ' +
            'pork pie, mud pie, cutie pie, mushroom and beef pie, ' +
            'are there other kinds of pie?'


SET @delta = REPLACE(@haystack, @needle, '')

--NB: Extra brackets to make order of opperations clear.
SELECT (len(@haystack) - len(@delta))  /  len(@needle) AS NumOccurances

---------------------------------------------------------------------------
Tuesday, September 06, 2005 3:32:58 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  |