Friday, July 9, 2010

Measure What Matters

I remember when I was in consulting some years ago now.  At the time, I was a fairly senior technical resource and I had a pretty wide variety of clients and scenarios under my belt.  I was... experienced.

Anyhow, as a consultant it is pretty common to be interviewed by your potential client before arriving.  Clients don't like to have total n00bs on the job if they are paying consulting rates.  I used to have a number of these sort of interviews before being accepted to work on a project.

Even though I forget exactly now which client it was that interviewed me, I still remember the interview.  At the time, .NET 1.1 was the norm and 2.0 was in beta or so.  I was interviewing for a technical position on corporate account - architect or senior dev, if I recall correctly.  The customer got me on a conference call and I breezed through the background portion of the interview.  Next came the 'technical' interview.  I apparently got some young buck, fresh from his MSCD.NET exam that decided to test me on .NET trivia.  After answering a number of general .NET questions correctly, he asked me two questions that stick in my mind:

  • What does 'private internal' mean?
  • If you were to throw a custom exception in .NET, how would you do it?

Now, I said at the time that I wasn't sure on the first one and that I thought it might be both private and internal visibility.  The interviewer delighted in telling me it was private OR internal (the UNION of the two).  For the next question, I said I would simply derive from Exception and do what I needed.  The interviewer again (with 'Aha!' in his voice) told me that (of course) I should derive from ApplicationException.

I was passed over for the role for not being technical enough.

Now, in retrospect, it is laughable.  First, you only need to be told once what something means in order for it to stick.  Next, it turns out I was right on the second one.  The interviewer was so caught up on catching me on what I didn't know that he never considered if it mattered.  To this day, I have never seen a single instance of using "private internal" on anything - ever.  Furthermore, he ignored the fact that I had a vast amount of experience in his industry and had demonstrated enough .NET knowledge to determine I wasn't joking when I said I had coded in it.

It would have been much better to ask meaningful questions that actually test what matters (in this case systems thinking):

  • When and why would you use a private and internal visible declaration - a.k.a. 'private internal'?
  • Why would you throw a custom exception in .NET?  When do you throw exceptions?

Those kinds of questions get much deeper into the psyche of the developer and let you understand what kind of developer you are dealing with.

I contrast this with my Microsoft interview.  I had one of the most intimidating interviews ever with Vittorio.  He asked me (paraphrasing), "How would you design Twitter?  Take some time and think about it - trivial answers without consideration will not bode well for you".  It was beautiful in hindsight.  I got to tell him about the architectural considerations that I thought mattered and in broad strokes what I thought about.  It must have worked - we are now on the same team and he is a good colleague and friend.  Had he asked me about advanced threading or WCF bindings, I might not have 'passed' his exam.  Turns out that those topics don't matter for the job.  He asked exactly what did matter - could I think about systems as a whole and I did I have enough understanding of the pieces?

Next time you interview someone, make sure you measure what matters.

Wednesday, February 3, 2010

How Do I Stop the Billing Meter in Windows Azure?

This might come as a surprise to some folks, but in Windows Azure you are billed when you deploy, not when you run.  That means we don't care about CPU hours - we care about deployed hours.  Your meter starts the second you deploy, irrespective of the state of the application.  This means that even if you 'Suspend' your service so it is not reachable (and consumes no CPU), the meter is still running.

Visually, here is the meter still running:


Here is when the meter is stopped:


Right now, there is a 'free' offering of Windows Azure that offers a limited # of hours per month.  If you are using MSDN benefits for Windows Azure, there is another offering that offers some bucket of 'free' hours.  Any overage and you start to pay.

Now, if you are like me and have a fair number of hosted services squirreled around, you might forget to go to the portal and delete the deployments when you are done.  Or, you might simply wish to automate the removal of your deployments at the end of day.  There are lots of reasons to remove your deployments, but the primary one is to turn the meter off.  Given that re-deploying your services is very simple (and can also be automated), this is not a huge issue to remove the deployment when you are done.

Automatic Service Removal

For those folks that wish an automated solution, it turns out that this is amazingly simple when using the Service Management API and the Azure cmdlets.  Here is the complete, deployment-nuking script:

$cert = Get-Item cert:\CurrentUser\My\<cert thumbprint>
$sub = 'CCCEA07B. your sub ID'

$services = Get-HostedServices -Certificate $cert -SubscriptionId $sub

$services | Get-Deployment -Slot Production | Set-DeploymentStatus 'Suspended' | Get-OperationStatus -WaitToComplete
$services | Get-Deployment -Slot Staging | Set-DeploymentStatus 'Suspended' | Get-OperationStatus -WaitToComplete

$services | Get-Deployment -Slot Production | Remove-Deployment
$services | Get-Deployment -Slot Staging | Remove-Deployment

That's it - just 6 lines of Powershell. BE CAREFUL.  This script will iterate through all the services in your subscription ID, stop any deployed service, and then remove it.  After this runs, every hosted service will be gone and the billing meter has stopped (for hosted services anyway).

Monday, January 25, 2010

Supporting Basic Auth Proxies

A few customers have asked how they can use tools like wazt, Windows Azure MMC, the Azure Cmdlets, etc. when they are behind proxies at work that require basic authentication.  The tools themselves don't directly support this type of proxy.  What we are doing is simply relying on the fact that the underlying HttpRequest object will pick up your IE's default proxy configuration.  Most of the time, this just works.

However, if you are in an environment where you are prompted for your username and password, you might be on a basic auth proxy and the tools might not work.  To work around this, you can actually implement a very simple proxy handler yourself and inject it into the application.

Here is one that I wrote to support wazt.  To use this, add the following to your app.config and drop the output assembly from this project into your execution directory.  Note, this would work with any tool in .NET that uses HttpWebRequest under the covers (like csmanage for instance).


<!-- basic auth proxy section declaration area-->
<!-- proxyHostAddress="Auto" : use Internet explorer configuration for name of the proxy -->
  <sectionGroup name="proxyGroup">
    <section name="basicProxy"
             type="Proxy.Configuration.CustomProxySection, Proxy" />

  <defaultProxy enabled="true" useDefaultCredentials="false">
    <module type="Proxy.CustomProxy, Proxy"/>

  <basicProxy proxyHostAddress="Auto" proxyUserName="MyName" proxyUserPassword="MyPassword" />


Download the source here.

Monday, April 27, 2009

Overlooking the Obvious

I was trying to troubleshoot a bug in my worker role in Windows Azure the other day.  To do this, I have a very cool tool (soon to be released) that lets me peek messages.  The problem was that I couldn't get ahold of any messages, it was like they were disappearing right from under my nose.  I would see them in the count, but couldn't get a single one to open.  I was thinking that I must have a bug in the tool.

Suddenly, the flash of insight came: something was actually popping the messages.  While I remembered to shut down my local development fabric, I forgot all about the version I had running in the cloud in the staging environment.  Since I have been developing against cloud storage, it is actually a shared environment now.  My staging workers were popping the messages, trying to process them and failing (it was an older version).  More frustrating, the messages were eventually showing up again, but getting picked up before I could see them in the tool.

So, what is the lesson here:  when staging, use a different account than your development accounts.  In fact, this is one of the primary reasons we have the cscfg file:  don't forget about it.

Sunday, December 7, 2008

A Solution for your Secret Santa Needs

Every year, we siblings and their spouses (or significant others as the case may be) in the clan Dunn get together and exchange gifts.  Years ago, we decided that trying to get each person a gift was a bit burdensome and it diluted the value of the gift.  Instead, we decided to do the Secret Santa - each person getting a name and spending ~$50 on that person.

Well, we used to actually see each other before Xmas and pull names out of the hat.  Not so much anymore.  As such, it was getting harder and harder to pull names.  I tried setting up some programs, Excel sheets, etc. to pick names randomly and email, but I always ended up knowing who my Secret Santa was since I was the admin, and since I also didn't have time to put in fancy restrictions like 'no spouses' or 'no reciprocity' (i.e. A gets B and B gets A), people complained.

I found the solution:  The Secret Santa Random Name Generator

It will even hide the names from you and email the people on your behalf.  You can also list exclusions in the picker.  The really great part:  it's free and I don't have register for anything.  Admittedly, I have to give up an email address - but with the amount of spam I get already, I doubt this will turn the tide.

Wednesday, June 11, 2008

LINQPad - not just for LINQ

I officially love LINQPad.  Joe Albahari has done a great job of introducing a light weight tool that is great for learning and prototyping LINQ queries.  From what I gather, Joe and Ben Albahari built this tool as part of their book offering.  It was so useful, it has taken on a life of its own.

It may not be entirely obvious, but it turns out don't have to use LINQPad solely for LINQ queries.  You can actually prototype any type of snippet of code.  I have been using it now instead of SnippetCompiler (another great quick snippet tool).

As an example, here is how to use System.DirectoryServices snippets inside of LINQPad:

Hit F4 to bring up the Advanced Query Properties Window


Add the System.DirectoryServices.dll reference in the Additional References window, and then add "System.DirectoryServices" in the Additional Namespace Imports window.

Now, just type your code normally and hit F5 when you are done:


This is a great little tool to have as you can query databases, build LINQ expressions, and visually inspect the results that come back pretty easily.  Now, as you can see you can also execute arbitrary code snippets as well.  Highly recommended.

Monday, June 2, 2008

Continental Offers Million Miler Program

As a frequent flier and former Continental Platinum Elite member, I was always jealous of the American Airlines program where you got lifetime status on the airline whenever you achieved a million air miles with them.  However, I was browsing the FlyerTalk forum when I noticed this announcement.  I can't wait to see how far away I am on it (probably 600K or more away is my guess).

FlyerTalk Announcment

Wednesday, January 30, 2008

Internet Connection Sharing is Amazing

I am on the road this week, working from a hotel and Starbucks primarily.  My hotel provides a wireless connection throughout the building which is a great thing.  The downside is that it basically dies in the evening when everyone gets to the hotel and slows the pipe to a trickle.  The other major downside is that it is incompatible with Microsoft VPN software.  What to do?

I recently switched phone providers from T-Mobile to AT&T.  The reason for this was actually quite simple:  It was waaay cheaper to switch to AT&T, get a brand new Blackjack 2 phone along with the 3G network offered there (T-Mobile is GPRS only right now) than to remain a T-Mobile customer.

I remember reading from Omar about using ICS with the Blackjack 2, so I give it a try.

Wow, the AT&T 3G network is amazingly fast (~863 Kb/s down, ~281 Kb/s up) for a phone.  But more to the point, it is faster and more reliable that the hotel wireless, plus it lets me VPN into work to boot.  That feature alone is worth the price of admission.  It's a shame that the Blackjack 2 doesn't have any way of getting Hotmail into your messaging app or that they didn't include ICS by default.  But, using the hack that Omar pointed out goes a long way to fixing some of it.  Very nice...

Monday, November 12, 2007

IIS7 Remote Manager Access Denied Error

If you have been playing with the remote management capabilities in IIS7, you might run into an error where you are denied access to change anything from the remote client:



A quick investigation using ProcMon shows that "Local Service" is trying to modify the configuration file (web.config) in the managed directory and is being denied access.

Naturally, to fix this you need to give write access to "Local Service" for whatever application you are trying to manage.

Friday, September 14, 2007

Using SQLDependency objects with LINQ

A question came up the other day on how to get LINQ to SQL to participate in using the SQL Notification Services.  Of course, I didn't know, but Mike Pizzo from the ADO.NET team was kind enough to answer.  I figured it must be possible, and sure enough, it is.  Essentially, you have to create a SQL dependency context, which is very similar to a transaction context.  Any code that participates within that context will automatically be associated with the SQLDependency.  Create the dependency first, before any LINQ (or other data access technology).  Here is the relevant code (note: this code is not optimized, so you might want to do things like change the SQLDependency to static or pass it in so it won't be garbage collected).

    static class GlobalNotifications


        public static event OnChangeEventHandler OnChange;


        public static void InitializeNotifications(string connectString)


            // Initialize notifications


            // Create and register a new dependency

            SqlDependency dependency = new SqlDependency();

            dependency.OnChange += new OnChangeEventHandler(NotificationCallback);

            System.Runtime.Remoting.Messaging.CallContext.SetData("MS.SqlDependencyCookie", dependency.Id);



        internal static void NotificationCallback(object o, SqlNotificationEventArgs args)


            OnChange.Invoke(o, args);



There is also one major caveat to using this with LINQ: Beware of complex queries that can be easily generated using LINQ.  The Query Processor will invalidate the command and fire an error event saying it was too complex.  Since you can easily generate lots of complex queries using LINQ (part of its power really), you need to really be cognizant of this limitation.

Friday, March 30, 2007

IIS7 and 404.3 Error

Here is something that I am sure developers will run into as they start to create web sites on their local Vista boxes using IIS7.  I thought I would just put this out here to save people some time.  If you are like me, you will go to the 'Turn Windows features on or off' selection and simply check the IIS7 option like so:

If done correctly, this installs the ASP.NET environment and all the appropriate stuff.  If not, you get an interesting error when you browse to the first .aspx page on your site.  Specifically, you will get a nice 404.3 error similar to this:

The part that should tip you off that something is completely misconfigured  is the part of the the error message (which are sooo much nicer these days) where the module is being reported as the "StaticFileModule".  Static files are things like .html files, jpegs, etc. where we are not performing any server side logic.  We know that our .aspx files need to be processed by the .NET runtime, so we should see something else as the handler there.

Now, here comes the confusing part.  Bring up the IIS Manager (Windows Key > "Inetmgr"), and view the Handler Mappings for your site and you will see something similar to this:

Notice that all of the ASP.NET extensions are missing?  There are no handlers defined for the .aspx, .asmx, .ashx or any other .NET extensions.  If you bring up the handlers installed on the machine however, you will see that they are all just fine:

At this point, you may be like me and scratching your head asking, "why are my handlers not being inherited correctly"?  If you are like me, then you will probably try delete your web app and then re-add it back.  When that fails you will try to uninstall and reinstall IIS7 again.  When that doesn't work, you will try to reinstall ASP.NET manually from the command line using "aspnet_regiis -i" or something similar.  When that fails, you will spend hours on Google trying to see what other people have done.  It might also cross your mind to just add them manually to your configuration.  If you are like me, however, that seems dirty and you will keep trying.

To save you some time, it actually turns out it is pretty easy to fix.  Simply DELETE the "Default Web Site", and then ADD it back.  The Handlers will be re-applied correctly and your virtual directory or web site will have all the correct handlers installed.  It is confusing why this even happens with a fresh install, but it appears to be a frequent occurrence according to Google searches.  Coming from IIS 5.1 and 6, it might be counterintuitive to delete a site, but this is actually not a big deal in Vista since you can have as many of these as you like (no artificial limits anymore).  I hope this saves someone some time.

Note to the IIS7 teamman, it would really be nice if you had a button that said something like "apply inherited handlers" or something like that.

Tuesday, January 30, 2007

Vista through Remote Desktop

One word...awesome.  While you don't get Aero or anything like that, it properly scales the display to my 24" Dell monitor at home and looks fantastic through RDS.  I have been typing so much lately that I decided I needed my larger monitor and natural keyboard from home.  My wrists were killing me from typing on my laptop keyboard.  I didn't realize how much I needed the natural keyboard.

Monday, January 29, 2007

Free T-Mobile HotSpot Access

Users of Windows Vista (of which I am) are entitled to receive 90 free days of T-Mobile Wifi access at any HotSpot location starting today.  Since there are like 2.8 billion Starbucks locations in the US alone (all of which are HotSpots), this means you have pretty good chances of being able to redeem this offer (at least in Seattle where approximate 1.3 billion of those Starbucks are located).

I signed up today thinking there would be an elaborate process to confirm that I was running Vista.  I was imaging some applet like that horrid WGA (Windows Genuine pain-in-the-Ass) that keeps popping up everywhere.  Luckily, no such garbage.  In fact, it appears that T-Mobile is validating eligibility by a simple browser agent check.  While the average user might not know how to change that browser string, you can bet a number of users do know how (Firefox has some great ones).  I suppose T-Mobile doesn't really care too much at this point or they would have done it differently.

Friday, July 28, 2006

A Good FTP Program

Omar asks is anyone knows of a good FTP program in this post.  Similar to Omar, I was getting sick of the nagging that SmartFTP performed each time I started it.  Even more annoying was when it refused to launch (ala Reflector.NET) until I performed an upgrade.  I asked around and everyone and their brother recommended FileZilla.  I suppose I am the lone voice of dissent on this one.  I actually tried to like FileZilla, but had to uninstall it rather quickly.  It just didn’t do things like I expected.  I couldn’t drag items into windows and back, and other assorted quirks that I forget now.  I really wanted to like it, but just couldn’t.

I almost went back to SmartFTP until someone mentioned Novell’s NetDrive application.  I tried this and never looked back.  It is a simple idea really.  It maps a drive to a remote FTP location and you use Windows Explorer like you would anything else.  It works great.  If you were to type “Novell Netdrive” into your favorite search engine, you would find plenty of places that host this particular very handy app.

Monday, July 24, 2006

A Recursive Pattern For DN Syntax Attributes Part 2

I am revisiting this particular topic once again to finish it up.  Last time, we established a general pattern for searching any DN syntax attribute in Active Directory or ADAM and chasing down all the nested results in either direction (i.e. forward link to back link or vice versa).  The solution worked well with one caveat:  intermediate values.  We often do not want to capture the intermediate values, but only the end results.  As an example, if we were to expand the group membership for a group object (the ‘member’ attribute) to discover the users, we would not want to include the other nested groups as values in our results, but we would only want to include the users in those nested groups.  In other words, we would want to exclude the intermediate values.  This is different than another example, say of discovering an org chart by expanding the ‘directReports’ attribute where we would clearly want to know all the intermediate reports.

For the specific example of expanding a group object to get membership, I posted an example in the book that used recursion and specifically excluded the result if the ‘objectClass’ was ‘group’.  I posed the question, “was this necessary?”.  Or more specifically, “can we create a general solution that will deal with both cases for intermediate values?”

The answer, of course, is yes.  We can pretty easily create a solution that will allow us to keep the intermediate values or discard them if we want.  In the general case, we do not need to know the object types.  In our example in the book, I think it was more clear what was happening by putting knowledge of the object type.  However, it also could have been solved with a simple boolean and no knowledge of the objects themselves.  Here is the revised solution.  I am omitting the IADsPathname interface this time, but you can easily pull it from the last post.

public class RecursiveLinkPair


    DirectoryEntry entry;

    ArrayList members;

    Hashtable processed;

    string attrib;

    bool includeAll;


    public RecursiveLinkPair(DirectoryEntry entry, string attrib, bool includeIntermediate)


        if (entry == null)

            throw new ArgumentNullException("entry");


        if (String.IsNullOrEmpty(attrib))

            throw new ArgumentException("attrib");


        this.includeAll = includeIntermediate;

        this.attrib = attrib;

        this.entry = entry;

        this.processed = new Hashtable();







        this.members = Expand(this.entry);



    public ArrayList Members


        get { return this.members; }



    private ArrayList Expand(DirectoryEntry group)


        ArrayList al = new ArrayList(5000);


        DirectorySearcher ds = new DirectorySearcher(



            new string[] {



                "objectClass" },




        ds.AttributeScopeQuery = this.attrib;

        ds.PageSize = 1000;


        using (SearchResultCollection src = ds.FindAll())


            string dn = null;

            foreach (SearchResult sr in src)


                dn = (string)



                if (!this.processed.ContainsKey(dn))


                    this.processed.Add(dn, null);


                    if (sr.Properties.Contains(this.attrib))


                        if (this.includeAll)



                        SetNewPath(this.entry, dn);








        return al;



    //we will use IADsPathName utility function instead

    //of parsing string values.  This particular function

    //allows us to replace only the DN portion of a path

    //and leave the server and port information intact

    private void SetNewPath(DirectoryEntry entry, string dn)


        IAdsPathname pathCracker = (IAdsPathname)new Pathname();


        pathCracker.Set(entry.Path, 1);

        pathCracker.Set(dn, 4);


        entry.Path = pathCracker.Retrieve(5);



This simple class uses the AttributeScopeQuery option to enumerate the attribute and then uses the utility interface IADsPathname to reset the entry as we recurse the results.  So, we now finally have a generic solution that will work on all DN syntax attributes in both directions and with or without intermediate values.

Friday, March 31, 2006

DEC 2006 Wrap Up and Presentation Material

Joe and I had a great time on Wednesday presenting our talk on Directory Services Programming in .NET.  Being the first time that we have ever presented together, we did no know exactly how it would work out.  All in all, we felt it went pretty well.  Thanks to everyone that attended!

One of the cool parts for us was that our publisher sent over some draft copies of the book.  We knew our publisher was sending something, but we had thought it was a sample chapter or two.  It was quite surprising to open the box and find the full text!  Seeing your hard work in print for the first time almost gives you goose bumps.

As promised, I am attaching the presentation material to this post.  It includes the updated presentation that we used as well as all the samples that we used during it.  We actually did not get to one of the samples called Dirsync, which allows us to poll the directory periodically for updates, so check it out.

If anyone has questions on these samples or the topic itself, Joe and I can be reached through the MS newsgroups or the ASP.NET Forums.  I would also suggest checking out what I consider useful System.DirectoryServices resources.  I will try to keep that updated as I find more.

Thursday, December 22, 2005

The .NET Developer's Guide To Directory Services Programming

Keith beat me to it, but Joe and I have finally submitted the final manuscript.  We have some copy editing left, but the book is mostly baked.  It has been a long time in the making and we are very fortunate to have had some great reviewers like Keith giving us advice along the way.

There were a lot of things that we wished we could have covered (perhaps in another book) more in depth.  It was a balancing act between trying to dump everything in our brains and not publishing a 900 page book.  The final page count is around 450 pages right now, which is big, but not too intimidating.

All in all, this was a good experience.  I did not know Joe very well when we started, but needless to say, we know each pretty well at this point and are good friends.  I think the partnership worked pretty darn well for two first-time authors collaborating mostly over email and wiki.  Joe knows his Directory Services very well and it would not nearly be the same book without him.  Keith was slightly off in his description (it was over a year ago), but I knew about Joe from the newsgroups (where he was dropping some serious knowledge) and had suggested to Keith to contact him as the second author of this book.  It was a great decision and I am glad Joe took it.

So, what is in the book?  Pretty much all the basics for System.DirectoryServices, like binding, searching, reading and writing attributes.  We cover the more advanced searches and data type marshaling as well as schema considerations and a discussion of security as well.  Finally, we cover a more scenario, or ‘cookbook’ approach for the more popular topics like user and group management as well as authentication.  We know what problems most users have and we try to address them in the scenarios.

Most of the samples in the book are going to be using System.DirectoryServices, though we do cover in places how to do things using the .Protocols namespace.  Additionally, we have one chapter that gives developers a view of what is there in the .ActiveDirectory namespace that they might use (it is mostly for administrators).

It is important to know that this is truly a guide and we could not cover every single scenario.  As part of the book’s website (or this blog), we will be adding new scenarios and how they can be accomplished as well.  Additionally, we are going to release some very cool code that developers will be able to use in their own applications.

As always, we can be found in either the forums ( or the newsgroups (microsoft.public.adsi.general).  I am not usually on the newsgroups, but Joe camps there.


Tuesday, November 1, 2005

A solution for loquacious co-workers

I subscribe to some internal mailing lists at work.  Oftentimes they are informative, sometimes amusings, but lately they have just become increasingly annoying.  I think I finally found the solution.  Essentially, it is a Do-Not-Disturb sign on the inane blatherings of a few mildly annoying individuals.

I am going to give it a shot as soon as Omar releases it to see how it works.  Right away I can think of another feature I would like it to have:

  • I want the ability to mark messages not only by thread, but by individual.  Certain individuals seem to have nothing better to do than spam the mailing lists and annoy everyone.  This way the thread could be killed regardless of subject if it was originated by someone.
Unfortunately for me, most of my email access during work hours is using OWA, so this won't help me there.  At least my hours in the evening will hopefully be less painful when using the full client.

Friday, October 14, 2005

More Gmail uses

I ran across this link today concerning a bunch of Gmail ‘hacks’.  It seems like Google does not care too much about people extending their system beyond its original uses.  A case of a very wise service provider, IMO.,1558,1871053,00.asp


Tuesday, September 20, 2005

Google as a spam filter

Skonnard points out that you can forward your personal email accounts to your Gmail account and then access Gmail via POP again to have it filter your spam out.  Additionally, you gain the benefit of long term email storage and better searchability (although Lookout does well for me).  This is probably an unintended use, but quite useful.