CIMG7642The house is finished and the Verizon FIOS guy has just left. We're all set and I've tested at 15mbps down and 2mbps up. According to Verizon my account will be upgraded to 15 down and 15 up on the 19th of November. (You have to call if you want to upgrade.)

I've got details on FIOS from our first installation at the other house. At this house the installer came and and hooked up the ONT (Fiber Optic convertor) on the outside of the house. I had RJ45 cable pulled to the outside of the house but according to the installer they prefer to use Coax for the last lengths between the ONT and the router in the house. So he ended up going...

Street Fiber->ONT->Coax->Router->RJ45

...just like this diagram. We borrowed on of the extra Coax cables and put the new router (still an ActionTec, but a nicer model) into the hinged bracket at the bottom of the wiring closet. The router is a bridge between the Coax and the RJ45. We plugged it into the router and checked the house's network drops. I turned off WEP and turned on WPA for Wireless Security. Next I'll plug in our VOIP adapter and turn on QoS (Quality of Service.)

I also mounted a UPS (battery) on the wall below the closet to make sure we keep connectivity if the power goes out. The ONT outside has a UPS of its own, but that UPS is woefully underpowered. If you want to keep your FIOS up, get another wall-mounted UPS and plug Verizon's little one into it.

Open Closed

CIMG7640The wiring guys did a great job and labeled everything just like I like it. Nice and organized. That's the #1 tip in all of this - stay organized. We've got labels at the end of each cable marking what it's for as well as permanent ink written on the cables themselves.

The next step will be hooking up all the computers and running a traffic generating program to flood the network and see if the Netgear switch (the one folks in the comments were concerned was suboptimal) holds up.

This is going to be fun. It's odd how hooking up water and power and sewer are trivial and boring but when Internet gets hooked up, suddenly this empty house has potential. We'll move in completely in 10 days.



I was messing around with some log files for the podcast and exported a CSV. There's lots of ways for us to get stats, but I was just poking around.

Given a CSV format like this:

"File","Hits","Bandwidth"
"/hanselminutes_0026_lo.wma","78173","163625808"
"/hanselminutes_0076_robert_pickering.wma","24626","-1789110063"
"/hanselminutes_0077.wma","17204","1959963618"
"/hanselminutes_0076_robert_pickering.mp3","15796","-55874279"
"/hanselminutes_0078.wma","14832","-1241370004"
"/hanselminutes_0075.mp3","13685","-1840937989"
"/hanselminutes_0075.wma","12129","1276597408"
"/hanselminutes_0078.mp3","11058","-1186433073"

And noticing that there are different file extensions, but one logical show...for example there's an MP3 of Show 76 and WMA of that same show I wanted to find out how many downloads per show.

I fired up PowerShell. First I can bring in the CSV file and notice that it's parsed into a PowerShell object list nicely:

PS C:\> import-csv File.csv | Select File,Hits

File                                                        Hits
----                                                        ----
/hanselminutes_0026_lo.wma                                  78173
/hanselminutes_0076_robert_pickering.wma                    24626
/hanselminutes_0077.wma                                     17204
/hanselminutes_0076_robert_pickering.mp3                    15796
/hanselminutes_0078.wma                                     14832
/hanselminutes_0075.mp3                                     13685
/hanselminutes_0075.wma                                     12129
/hanselminutes_0078.mp3                                     11058

Notice that there are headings in this output? PowerShell's Import-CSV is smart enough to infer the headers and positions and split things up. After the first | pipe I don't ever have to think CSV again.

I'm going to need a new column, though, called Show with the Show number it in. I'll probably glean it from the Filename. Just to get started, I'll make a new "calculated column."

PS C:\> import-csv file.csv | select File, Hits, @{Name="Show";Expression={ $_.File } }

File                                    Hits    Show
----                                    ----    ----
/hanselminutes_0026_lo.wma              78173   /hanselminutes_0026_lo.wma
/hanselminutes_0076_robert_pickering... 24626   /hanselminutes_0076_robert_pickering...
/hanselminutes_0077.wma                 17204   /hanselminutes_0077.wma
/hanselminutes_0076_robert_pickering... 15796   /hanselminutes_0076_robert_pickering...
/hanselminutes_0078.wma                 14832   /hanselminutes_0078.wma
/hanselminutes_0075.mp3                 13685   /hanselminutes_0075.mp3
/hanselminutes_0075.wma                 12129   /hanselminutes_0075.wma
/hanselminutes_0078.mp3                 11058   /hanselminutes_0078.mp3
/hanselminutes_0077.mp3                 11003   /hanselminutes_0077.mp3
/hanselminutes_0074.mp3                 6494    /hanselminutes_0074.mp3

Except you can see that while I have a new column called "Show" it's just got the File duplicated. Notice the format for making a new Column:
select File, Hits, @{Name="Show";Expression={ $_.File } }.

Inside that { } scriptblock I need to do my work to get a show number.

It's a classic joke, so I'll say it again: "So you've got a problem and you've decided to use Regular Expressions to solve it. Now you've got two problems."

The show format has changed a bit over the years and some have leading zeros, some have names at the end. It's organic. So, in front of the expression we add a Regular Expression. You can make them easily in PowerShell by putting [regex] in front of a string. The ; is just a separator between statements. The first statement is just the assignment of a RegEx to a variable called $re. Later in my script block I apply that RegEx to the $_.File (remember that $_ is the equivalent of "this" in PowerShell, so $_.File is this.File).

The @{Name="Value";Name="Value"} format is how to express a Hashtable to PowerShell.

PS C:\> $re =[regex]"\d{2}(?=[_.])"; import-csv file.csv | 
        select File, Hits, @{Name="Show";Expression={$re.matches($_.File)[0] } }

File                                    Hits     Show
----                                    ----     ----
/hanselminutes_0026_lo.wma              78173    26
/hanselminutes_0076_robert_pickering... 24626    76
/hanselminutes_0077.wma                 17204    77
/hanselminutes_0076_robert_pickering... 15796    76
/hanselminutes_0078.wma                 14832    78
/hanselminutes_0075.mp3                 13685    75
/hanselminutes_0075.wma                 12129    75
/hanselminutes_0078.mp3                 11058    78
/hanselminutes_0077.mp3                 11003    77
/hanselminutes_0074.mp3                 6494     74

The RegEx "\d{2}(?=[_.])" says "find me the first two decimals to the left of either a "_" or a "." It's not foolproof, at least not until show 100, but this is a Poor Man's Solution.

Next, I'll sort by Show descending then group all the like shows together.

PS C:\> $re =[regex]"\d{2}(?=[_.])"; import-csv file.csv |
        select File, Hits, @{Name="Show";Expression={$re.matches($_.File)[0] } } | 
        sort Show -desc | group Show

Count Name  Group
----- ----  -----
    9 79    {@{File=/Hanselminutes_0079.wma; Hits=27; Show=79},...
   12 78    {@{File=/hanselminutes_0078.m4b.torrent; Hits=18; Show=78},...
   12 77    {@{File=/hanselminutes_0077.wma.torrent; Hits=52; Show=77},...
   18 76    {@{File=/hanselminutes_76.mp3; Hits=1; Show=76}, ...
   11 75    {@{File=/hanselminutes_0075_lo.wma; Hits=468; Show=75},...

In this listing I can see via Count that there were 9 different formats of Show 79 downloaded in this time period. However, the good data is trapped in the Group column. All my previous line items are grouped in there. I need to sum up all the Hits for all the downloads of the the 9 different formats of Show 76...and all the shows.

PS C:\> $re =[regex]"\d{2}(?=[_.])"; import-csv file.csv |
    select File, Hits, @{Name="Show";Expression={$re.matches($_.File)[0] } } | 
    sort Show -desc | group Show | 
    select Name,{($_.Group | Measure-Object -Sum Hits).Sum }

Name   ($_.Group | Measure-Object -Sum Hits).Sum
----   ------------------------------------------
79      9205
78     27575
77     29807
76     42798
75     27174
74     13060
73     10532
72     10145
71      9826
70      8745
69      8065
68      8132
67      7024
66      8535
65     13041

Now, I select out Name and then take each item's Group (remember $_ is this, so $_.Group means "the current item's Group." Each item will go through Measure-Object which has options like -sum and -average, etc. We grab them up and Sum them.

But the Column Header looks silly. I want a pretty name.

PS C:\> $re =[regex]"\d{2}(?=[_.])"; import-csv file.csv |
    select File, Hits, @{Name="Show";Expression={$re.matches($_.File)[0] } } | 
    sort Show -desc | group Show |  
    select Name,
    @{Name="Hits";Expression={($_.Group | Measure-Object -Sum Hits).Sum }}

I just make a Hashtable with the Name "Hits" and put the scriptblock in a key called "Expression." Add some more sorting and:

Name   Hits
----   ----
26     78673
76     42798
77     29807
78     27575
75     27174
74     13060
65     13041
73     10532

Now I can see that show 76 got 42798 downloads this time period and the classic show 26 did nicely with 78673.


It this representative of the way you SHOULD do things in PowerShell? No, but it's a transcript of a real-life problem being together at the command line. It took less time than it would take to write a C# program and it's easily modified ad-hoc. Here's what Lee Holmes said he would have done, accomplishing the same thing not as a one-liner but as a proper PowerShell function:

function Get-ShowHits
{
  $regex = '/hanselminutes_(\d+).*'
  $shows = Import-CSv File.csv | Select File,Hits | Group { $_.File -replace $regex,'$1' }
  foreach($show in $shows) 
  {
    $showOutput = New-Object System.Management.Automation.PsObject
    $showOutput | Add-Member NoteProperty Name $show.Name
    $showOutput | Add-Member NoteProperty Hits ($show.Group | Measure-Object -Sum Hits).Sum
    $showOutput
  }
}
Get-ShowHits | Sort -Desc Hits

Both are great examples of why PowerShell rocks my world. When are you going to try it? I swear, everyone has "been meaning to try PowerShell but I haven't had the time." Just do it.



In my new ongoing quest to read source code to be a better developer, I now present the tenth in an infinite number of a weekly series called "The Weekly Source Code." Here's some source I'm reading this week that I enjoyed.

Our theme this week is "Patterns Considered Harmful" with examples of source doing things we're "not supposed to do."

  • ÜberUtils - Strings from Brad Vincent. Don't like System.String? Well, spot-weld a bunch of useful stuff onto it with C# 3.0 Extension Methods. Brad starts to talk about how his utils might be Considered Harmful:

    "Now I know some people might argue that this is extension method abuse, but look at how much more power my strings have...and anything that helps me code quicker and smarter is not abuse in my book - it's smart coding!"

    Here's just two of his many useful additions you can hardly consider harmful:
            public static string XOR(string input, string strKey)
            {
                if (IsEmpty(input)) return input;
                string strEncoded = string.Empty;
                int nKeyIndex = 0;
                for (int i = 0; i < input.Length; i++)
                {
                    strEncoded += Convert.ToChar(input[i] ^ strKey[nKeyIndex]);
                    nKeyIndex++;
                    if (nKeyIndex == strKey.Length) nKeyIndex = 0;
                }
                return strEncoded;
            }
    
            public static string ToTitleCase(string Input)
            {
                return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(Input);
            }
  • This item isn't source, but rather a study topic. I saw that Jeff Atwood had a recent post on "Considered Harmful" docs and mentions the seminal GOTO considered harmful paper. Take a free moment and go read the interesting January 2003 thread of discussion between a number of programmers and Linus Torvalds, creator of Linux about Linus's use of GOTO in the Linux Kernel. Why? Here's a teaser from Linus:

    "No, you've been brainwashed by CS people who thought that Niklaus Wirth (Editor: Author of GOTOs Considered Harmful) actually knew what he was talking about. He didn't. He doesn't have a frigging clue."

    > I thought Edsger Dijkstra coined the "gotos are evil" bit in his
    > structured programming push?

    Yeah, he did, but he's dead, and we shouldn't talk ill of the dead. So these days I can only rant about Niklaus Wirth, who took the "structured programming" thing and enforced it in his languages (Pascal and Modula-2), and thus forced his evil on untold generations of poor CS students who had to learn langauges that weren't actually useful for real work.
    - Linus

  • Putting everything all on one line. I'll do a separate post on this, but Lee Holmes (author of the Windows PowerShell Cookbook) and I were doing some PowerShell recently, parsing CSV files and did this. Lee doesn't recommend it, but I think it's pretty:
  • Import-CSv File.csv | Select File,Hits | Group { $_.File -replace '/hanselminutes_(\d+).*','$1' } | Select Name,{ ($_.Group | Measure-Object -Sum Hits).Sum }

Feel free to send me links to cool source that you find hasn't been given a good read.



blogging Are you in King County/Seattle/Redmond/Bellevue and surrounding areas? Are you a huge nerd? Perhaps a geek? No? Maybe a spaz, dork, dweeb or wonk. Maybe you're in town for an SDR (Software Design Review) or the PNP Summit. Quite possibly you're just a normal person.

Regardless, why not join us for some Mall Food at the Crossroads Bellevue Mall Food Court on November 8th around 6:30pm? You can even help me write my speech that I have to give that Friday. ;)

Here's some links to help you remember and add this to your calendar:

Feel free to RSVP in the comments. If you want to come and share something with the group, please do! We're language and technology agnostic and always eager to learn about new stuff.

I've only been at Microsoft 7 weeks now and it'd be great if more Microsoft people came - everyone loves to put a face to a blog and sometimes Microsoft folks get tunnel vision and don't learn about what's going on in other groups! Blue Badges welcome...Please spread the word!

Hope to see you there. If not, I shall eat my Spicy Chicken alone in peace.

UPDATE: You might also want to check out the Seattle Code Camp this November 17 and 18th. You can register here. For some reason there's a certificate error on their site, looks like a problem with their SSL.  I know the guys who run it, so I wouldn't worry about the error, I'm sure it'll be fixed soon.



3271123971My eighty-sixth podcast is up. In this one we turn to Jonathan Zuck, President of the Association for Competitive Technology to demystify Software Licensing and the industry's many Open Source Software Licenses. Jonathan also talks about their Innovators Network and what it can do for entrepreneurs.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

If you have trouble downloading, or your download is slow, do try the torrent with µtorrent or another BitTorrent Downloader.

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Check out their UI Suite of controls for ASP.NET. It's very hardcore stuff. One of the things I appreciate about Telerik is their commitment to completeness. For example, they have a page about their Right-to-Left support while some vendors have zero support, or don't bother testing. They also are committed to XHTML compliance and publish their roadmap. It's nice when your controls vendor is very transparent.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?



Just a reminder: Release builds are not Debug builds. Seems obvious, but it's worth saying again. Release builds are optimized for speed and debug builds are optimized for, well, debug-ability. However, most of the optimizations in managed code are done by the JIT compiler rather than the language compiler.

However, sometimes in our zealous attempts to make Release builds easier to debug we can inadvertently (or totally "vertently") remove a lot of the optimizations that make Release builds faster.

Introduction

I was talking to Jeremy and he had come upon some code that was inserting a try{} catch() { throw; } block in every method. The rationale was that "they wanted the complete stack trace in their logging after an exception was thrown." That's a noble goal, but their technique of adding these guards is what's called an "anti-pattern" or as Egon would say "it would be bad." An anti-pattern is "a pattern that tells how to go from a problem to a bad solution."

First, let's start by exploring why they aren't getting "a complete stack trace" before we tackle why they believe they want/need a complete one.

Here's a simple program:

using System;

class NormalProgram
{
    static void Main(string[] args)
    {
        try
        {
            methodA();
        }
        catch (System.Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
    static void methodA() { methodB(); }
    static void methodB() { methodC(); }
    static void methodC() { badMethod(); }
    static void badMethod() { throw new ApplicationException("generic bad thing"); }
}

In this program, Main calls A, then A calls B, which calls C, which calls badMethod which throws an exception. That exception is caught up at Main. So far, makes sense right?

We'll compile two versions, one in Debug mode and one in Release and run them on a regular 32-bit machine. Notice we're saying /o for enable optimizations for the Release build. We are making debug symbols for Release via /debug:pdbonly, but it doesn't affect performance in a significant way.

"%FXROOT%\csc.exe" /t:exe /out:NormalRelease.exe /debug:pdbonly /o NormalProgram.cs
"%FXROOT%\csc.exe" /t:exe /out:NormalDebug.exe /debug NormalProgram.cs

We run Debug on 32-bit and we see:

System.ApplicationException: generic bad thing
   at NormalProgram.badMethod() in NormalProgram.cs:line 24
   at NormalProgram.methodC() in NormalProgram.cs:line 23
   at NormalProgram.methodB() in NormalProgram.cs:line 21
   at NormalProgram.methodA() in NormalProgram.cs:line 19
   at NormalProgram.Main(String[] args) in NormalProgram.cs:line 11

Looks good, makes sense. Now we run Release on 32-bit:

System.ApplicationException: generic bad thing
   at NormalProgram.badMethod() in NormalProgram.cs:line 24
   at NormalProgram.Main(String[] args) in NormalProgram.cs:line 11

Our call stack has been "collapsed"? Does it make it harder to debug? Not really, because we knew where we ended up and the path between the two is clear (otherwise this "inlining" wouldn't have happened.)

However, it is confusing and there's a perception that "information is missing." It's important to note that information isn't missing but rather this stack trace is showing the runtime reality. What you write (the Programmer's Intent) isn't exactly what runs, especially when things are optimized. As programmers we are doing our best to tell the machine what to do and it is doing its best to do that fast and correct - let it do what it does best. When we see a stack like this our first reaction is that information is there, but has been hidden. In fact, the code we wrote ran, but not every method got their own local stack frame as they were optimized into fewer methods.

Inlining

Disclaimer: I'm showing you this for informational purposes. Doing this without thinking or having a good reason is usually  a bad idea and could confuse other issues. The only reason you might want to do this would be if you were doing some kind of funky thing that made your method require its own stack space. DON'T ADD THIS ATTRIBUTE WILLY-NILLY. Don't Program By Coincidence. Remember the point of this post is that Release and Debug are different. Use them differently.

What if I tell the runtime JIT-ter to not inline? I'll add one line and one using:

using System;
using System.Runtime.CompilerServices;

class NormalProgram
{
    static void Main(string[] args)
    {
        try
        {
            methodA();
        }
        catch (System.Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
    [MethodImpl(MethodImplOptions.NoInlining)]
    static void methodA() { methodB(); }
    static void methodB() { methodC(); }
    static void methodC() { badMethod(); }
    static void badMethod() { throw new ApplicationException("generic bad thing"); }
}

And run on 32-bit:

System.ApplicationException: generic bad thing
   at NormalProgram.badMethod() in NormalProgram.cs:line 24
   at NormalProgram.methodA() in NormalProgram.cs:line 19
   at NormalProgram.Main(String[] args) in NormalProgram.cs:line 11

Well, that stopped the inlining of method A, but of course B and C are still inlined. You can see how this is going to get icky.

ASIDE: We as programmers have all reached this moment. This is the moment when we decide whether or not to slap an attribute on every method in our program. (This attribute is just an example, but you know this moment...there's still time to actually stop and try to understand the problem...)

...but we have to ship. So, let's try this:

using System;
using System.Runtime.CompilerServices;

class NormalProgram
{
    [MethodImpl(MethodImplOptions.NoInlining)] 
    static void Main(string[] args)
    {
        try
        {
            methodA();
        }
        catch (System.Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
    [MethodImpl(MethodImplOptions.NoInlining)]
    static void methodA() { methodB(); }
    [MethodImpl(MethodImplOptions.NoInlining)] 
static void methodB() { methodC(); } [MethodImpl(MethodImplOptions.NoInlining)] static void methodC() { badMethod(); } static void badMethod() { throw new ApplicationException("generic bad thing"); } }

And compile and run as Release on 32-bit...

System.ApplicationException: generic bad thing
   at NormalProgram.badMethod() in NormalProgram.cs:line 24
   at NormalProgram.methodC() in NormalProgram.cs:line 23
   at NormalProgram.methodB() in NormalProgram.cs:line 21
   at NormalProgram.methodA() in NormalProgram.cs:line 19
   at NormalProgram.Main(String[] args) in NormalProgram.cs:line 11

Now we're back where we were before, right? Well, not really. We've got the full stack again, but we've neutered the build such that the JITter can't really do it's job.

Plus, we haven't tried 64-bit yet. Let's run the Release build on 64-bit:

System.ApplicationException: generic bad thing
   at NormalProgram.methodC() in NormalProgram.cs:line 23
   at NormalProgram.Main(String[] args) in NormalProgram.cs:line 11

Weird. One conclusion to draw would be that 64-bit CLR ignores method inlining attributes. That's not necessarily the case. Another would be that 64-CLR is more aggressive about inlining. The deal is that there are MANY optimizations that the JITter can to. MANY. They wouldn't give me a number because it's Special Sauce, but le's just say it's not one or two. It's more than that. ;)

Inlining isn't the only thing that can "collapse" a call stack like this. This also isn't exactly true. In this case, remember that x64 is a whole new processor architecture while x86 has been around for, let's say, a while. Turns out that x64 really likes to optimize and this is an example of a "Tall Call Optimization" rather than explicit Method Inlining.

Be sure to read David Broman's detailed blog post on exactly x64 tail-call optimizes and when it doesn't.

A good explanation from The Original Wiki at the Portland Pattern Wiki:

"Tail-call optimization (or tail-call merging or tail-call elimination) is a generalization of TailRecursion: If the last thing a routine does before it returns is call another routine, rather than doing a jump-and-add-stack-frame immediately followed by a pop-stack-frame-and-return-to-caller, it should be safe to simply jump to the start of the second routine, letting it re-use the first routine's stack frame (environment)...."

"However, TailCallOptimization has some drawbacks. The runtime environment will have a confusing stack during execution of tail-called routines, which can make debugging difficult ("How did I get here? baz() never even calls foo()!")."

The wiki explanation was written with C in mind, but the concept is universal and it's the "confusing stack during execution of tail-called routines" that's got me writing this blog post today.

There's some controversy on whether Tail Call Optimizations are a subset of Method Inlining. That may never be resolved, but for now they are discrete and different. Eric Gunnerson has a good article on some of the heuristics that the JIT uses in its inlining decision making process.

For some hardcore details, be sure to read David Notario's excellent series on x86 JIT inlining from 2004, both Part 1 and Part 2. Perhaps start by reading his "The CLR x86 JIT, an overview" as he explains seven basic stages the x86JIT.

An Anti-Pattern

Now, back to our customer from the beginning who was inserting a try{} catch() { throw; } block in every method. Let's try that (don't do this at home):

using System;

class UglyProgram
{
    static void Main(string[] args)
    {
        try
        {
            methodA();
        }
        catch (Exception e)
        {
            Console.WriteLine(e);                
        }
    }
    static void methodA() { try { methodB(); } catch { throw; } }
    static void methodB() { try { methodC(); } catch { throw; } }
    static void methodC() { try { badMethod(); } catch { throw; } }
    static void badMethod(){throw new ApplicationException("generic bad thing");}
}

...and compile both Debug and Release and this produces the same output on both 32-bit and 64-bit:

System.ApplicationException: generic bad thing
   at UglyProgram.badMethod() in UglyProgram.cs:line 20
   at UglyProgram.methodC() in UglyProgram.cs:line 19
   at UglyProgram.methodB() in UglyProgram.cs:line 18
   at UglyProgram.methodA() in UglyProgram.cs:line 17
   at UglyProgram.Main(String[] args) in UglyProgram.cs:line 10

Why? Because by setting up the try's you're introducing the potential for other ways out of each method so the JIT'ter can't optimize anything that would collapse the call stack like we saw earlier. This isn't a good pattern as it doesn't deal with the underlying issue in a simple way. The customer wants to be able to debug Release builds easier.

Options

Here's some options we could try:

  • Try/catch every method - Not a good idea. Not only are you cluttering your code, but you're paying a cost all the time when you only need to debug in Production/Release occasionally.
  • Put [MethodImpl(MethodImplOptions.NoInlining)] on every method - Also not a good idea, not only because of the operative "every method" violating the DRY Principle but also because it only deals with one specific optimization out of many.
  • Turn off Optimizations in the compiler - This particular kind of inlining appears to be a JITter thing, not a language compiler thing so turns out that doesn't work in this instance.

Ok, so the customer wants a fuller call stack. I would propose that they in fact don't want this. One of my old bosses used to say:

"Customer walks in with a cell phone and says 'this thing needs a bigger antenna.' We have to ask ourselves does he want a bigger antenna or better cell phone reception" - Mark Klein

This is a great pithy analogy. Everyone comes in with both Problems and Solutions. This customer wants to be able to debug Release builds. They surely don't want full call stacks in Release Mode if it means turning off all optimizations.

Best Solution

One thing the customer could do that would give them the best of both worlds is something Mark Pearce told me about a while back, the [.NET Framework Debugging Control] section of an .ini file you've probably never used:

This JIT configuration has two aspects:

  • You can request the JIT-compiler to generate tracking information. This makes it possible for the debugger to match up a chain of MSIL with its machine code counterpart, and to track where local variables and function arguments are stored.
  • You can request the JIT-compiler to not optimize the resulting machine code.

If you have a file Foo.exe you can create a Foo.ini with these contents:

[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0

Implementation Detail: Why is it an INI file? Well, the .NET runtime hasn't started up yet, so we don't have all that XML-parsey goodness lying around. Instead they need to use the Win32 method GetPrivateProfileString() in order to retrieve those.

This solution assumes you compiled with /debug:pdbonly in Release mode in order to generate the full stack when needed.

DICSLAIMER: This isn't something you want to put into production! You'd only use this for debugging. It's something you'd enable on a case-by-case basis.



UPDATE: To be clear. This technique does NOT send macros in your email. It only flips a metadata bit in the message and that metadata is only transmitted within Exchange (within your company). It is not propagated to outside email addresses. It's better than BCC because it doesn't break local Outlook Rules. It's harmless.

I really hate it when I say "please send replies directly to me" and a Reply To All happens. It's not only a bummer for the person who sent it but also for everyone on the distribution list.

Trivia: At Microsoft they/we say "little-r" me when we want a reply directly to us or "Big-R" when we mean Reply To All.

I was thinking it'd be cool to have a button on my Outlook Message Form that prevented folks from Reply'ing to All or Forwarding the message. I poked around a bit trying to write an Outlook Macro and realized that I've completely overwritten all the brain cells that had previously held information about VBA macro programming. Seriously. I worked in VB3-6 for years. I was a ninja. Now I'm just an old fat guy with a Black Belt that used to fit. Anyway.

I asked for help and KC Lemson pointed me to Bill Jacob, both actual ninjas, and he took my Rube Goldberg-ian plan and turned it into two lines of code. Doh.

Here's "How to easily disable Reply To All and Forward in Outlook":

Go Tools|Macro|Macros...

image

In the next dialog, type something like NoReplyAll and click Create.

image

At this point, even when running Vista 64, you'll be magically transported back to 1996, completely with owner-draw non-standard gray toolbars and other bits of gray that will leak in from the past.

Add these lines to your new subroutine:

ActiveInspector.CurrentItem.Actions("Reply to All").Enabled = False
ActiveInspector.CurrentItem.Actions("Forward").Enabled = False

Then close this window.

image

At this point you've got a macro that prevents Replying to All and Forwarding (at least within Outlook world. This won't prevent folks running other mail systems from Replying to All, but we're mostly focused on internal work with this tip.)

Now, open up a new Outlook Message and right click at the VERY top (assuming Outlook 2007).

image

Click More Commands...now from this dialog select "Macros" from the dropdown, select your new Macro and click Add>>.

image

If you like, click on your Macro on the right and select the Modify button and pick a nice icon for it and a Display Name. I used a "halting hand" icon:

image

Click OK and look at your Quick Access Toolbar...you've got a nice little icon there.

image

Now, CLICK that button then send an email to yourself or a coworker...

image

Cool, mission accomplished. One less thing to worry about. Thanks Bill!



homeatlastWow. If you get a chance, here's a good reason to install Silverlight. Click on the picture of Carl Franklin at the right to see something pretty amazing.

It's Carl as a one-man-band playing piano, drums, bass and guitar, mixed together seamlessly into one amazing Hi-Def 720p video. Remember to double-click for fullscreen once you're in the player.

He explains the technical details on his blog. How he recorded it, which cameras, what programs and the final squishing with Expression Media Encoder. Here's the link to his original test and to

You wanna talk multi-talented? I need to learn the piano. Great job, Carl, truly amazing.



iisfastcgiphpHello Dear Reader. I have been working with IIS7 for a while and I'm convinced that it's the cat's pajamas[1]

I started playing with IIS7 and noticed that it had FastCGI support. This means I could plug in PHP or maybe Perl or even Ruby into IIS7. This would be nice because I could host my ASP.NET blog, but also drop in some of the nice open source PHP applications that are available for maybe a photo gallery or something, all hosted on the same IIS machine.

What I did was take Bill Staples blog post on FastCGI as a guideline and got IIS7, FastCGI and PHP running on my machine. I did three load tests, one with CGI, one with FastCGI and one with Kernal Output Caching (new IIS7 feature) turned on. This video shows a number of tools and how to configure IIS7 step by step.

You can watch the video/screencast on the new Hanselman Silverlight Player (thanks Tim!) or download the WMV directly. If you guys want more IIS7 videos in detail, give me feedback in the comments and I'll see what we can do about putting together a series over on http://www.iis.net.

FastCGI GoLive on IIS6

If you're running IIS5.1 or IIS6, there is a GoLive release available to put your PHP apps into production on IIS and FastCGI. If you've previously downloaded the FastCGI TP2 release, be sure to get the latest GoLive version for IIS5.1/6.

There's also an actively maintained FastCGI IIS Forum with members of the team and MVPs helping out.

FastCGI for IIS7

If you're running IIS7 on a non-SP1 Vista, you can get FastCGI as a download for x86 and x64 as well. However, if you're running Vista SP1 Beta, as I am in the video, or Windows 2008 RC0, then you've already got FastCGI. One less step, eh? Check it out in the video.

WCat (Web Capacity Analysis Tool) 6.3

In this video I use a tool call WCat that you can download in x86 and x64 flavors. It is very lightweight and can simulate thousands of concurrent users on even a laptop. I pushed my local IIS7 with caching to over 2000 requests a second. It's free, easy with a basic scripting language. It's a great way to beat on your development servers and do some powerful profiling. I loves me some free tools.

Screencast Survey

I have been thinking about doing a series of IIS7 screencasts to augment the very good articles on http://www.iis.net. If you haven't been over there, I recommend you check it out.

Anyway, if you've seen me speak on stage, you know I'm a visibility/accessibility wonk and I really like to think about how folks learn, etc. I've been working with Camtasia for a while now and doing some video editing in Sony Vegas. In the recent ALT.NET Videos I put myself in PIP (Picture in Picture) and the response (even though the video was very rough) was very positive. I think that PIP really adds a lot to a screencast, but only if combined with appropriate editing, callouts, zooming and moving/sizing of the PIP window to make sure nothing is obscured. I wonder if you agree?

I'm interested in both your thoughts and opinions on the FastCGI stuff but also on Screencasts in general:

  • I'd also like to try creating screencasts that look great at 640x480 but also would be viewable on a 320x240 screen using Zoom and Pan or a Viewfinder technique. Do you have any interest in that?
  • Are screencasts a big part of your learning process?
  • Does Picture in Picture add value to you?
  • Do you prefer a fairly casual screencast with PIP like I've done here, or a more formal greenscreen/floating head with a nice suit reading a script. This screencast was fairly "organic" on purpose because it's real. There's no fakery.

Thanks, Dear Reader.


[1] Cat's Pajamas - An adjective used by hipsters of the 1920's to describe a person who is the best at what they do. lso used to describe another person who is genial and fun to be with.
"Martin sure knows how to dance, he's the cats pajamas, man!""



CIMG7379 Looks like folks ARE interested in the Home Wiring topic. I'm not an expert, but I do read a lot. Here's some answers to some great questions in the comments.


Q: "Wooden walls... huh... wooden walls. Umm, right, whatever. But why don't you use tubes inside the wall that hold the wires?
Right now when you close the wall, you can't add new cables, right?
Over here in The Netherlands/Europe we embed tubes in the concrete or bricks so we are able to pull new wires through it." - Rutger

A: Sure, that's sometimes used. Usually instead we just pull WAY more cable that we'd need. Wooden walls "can" be opened (with trouble) and additional pulls can be "fished" through, but your point is well taken, this is a hassle. We've done a combination by pulling lots of wires, but also by including a 2" conduit (in orange in the picture) leading between floors as well as to the main entertainment center (TV).


Q: "what about sound isolation? Seems to me pretty noisy." - Rutger

A: The closet will just have the Home Server, Media Server, the switch and the wireless router. The servers are fairly quiet, but certainly not silent. I haven't given much thought to sound isolation in the wiring closet, instead focusing on the room I record Hanselminutes in. If it becomes a problem, first I'd add a sealing strip of rubber to the bottom of the door, and then I'd look at "blowing in" extra insulation in that one wall, and finally I'd line the one inward-facing wall with sound dampening material.


Q: "Let me guess - you handle the tech, while your wife is in charge of picking out the color scheme, window treatments, appliances, granite countertops, carpeting, landscaping, shower curtains, decor, and new furniture?" - Frank

A: Uh, gulp. Actually, if you knew some things about me you'd know I'd kind of a Nate Berkus about this stuff. I came up with most of the colors, the window treatments, all the appliances. Mo and I did the countertops (ceramic, not granite) and carpets together. I'll do most of the furniture and decor, accents and landscaping, fencing, etc, and she'll do art, photos, pictures, knick-knacks etc. I actually just spent my lunch hour at Bed, Bath, and Beyond.


Q: "I was a little surprised to see you getting a Netgear Switch. Netgear is a good consumer brand but they really don't have the chipsets to compete with the big boys such as Dell, HP, and Cisco. See through put is all dependent on how much the chipset can handle. Really what you want to look at is the switching capacity because it is totally different than bandwidth." - Nick

A: Hm. I picked up a nice Netgear GS724TS for literally nothing on Ebay. I can add more switches as I need to, and it has a switching capacity of 20Gbps. Even if I had every port full (I won't) with everything running at 1Gbps (I don't) I'd still be "ok." Sure I could have got an HP with 48Gbps capacity, but it seems overkill and was more money. The Dell you references only had an 8Gbps capacity, so I think I did well for very little money. Of course, the switch is just mounted into the closet, so it can always be popped out for the future, but I think 20Gbps is pretty reasonable.


Q: Also, designate where you electrical taps are and ensure your office has at least 3 dedicated circuits if you're going to have a reasonable amount of gear/UPS. I took the rule of a jack box a foot away from each power drop so that I didn't end up with wires all over the floor. For instance, I have three separate jack plates in my office alone, each with 2+ CAT5e jacks. The one by the server has 6 CAT5e jacks so that everything can have a dedicated drop to the switch to avoid overloading a single cable. - Chris

A: Totally agree. I've got two dedicated 20 amp circuits in my office and another 20 amp in the wiring closet.


Q: What model of switch do you have? You said it can do RJ11 ports, which sounds like a cool feature. - Tony

A: It's not the switch that does the RJ11, basically it's the punchdown block. There's a separate "hub" thing for RJ11, and if I want to change a Data Run into a Phone Run, I just move the run from the switch into the phone hub. Then can put RJ11 wires into an RJ45 in the room and I'm set. I'm moving off of Vonage now that they are imploding and going back to Verizon for phone service, but we'll be using Skype exclusively for our many overseas calls.


Again, I'm just stumbling through this, it's only the second time I've put together this kind of setup and the first time was only 8-ports and 100mbps, so I DO appreciate all your comments and (constructive) criticisms!



DevConnections/ASPConnections 2007 in Vegas

Posted 2007-10-22 11:20 PM in ASP.NET | Speaking.

POST UPDATED: Scroll down...

LVFALL07DEVCELL05 Looks like it's official and my second conference speaking gig (or perhaps first, because technically ALT.NET wasn't speaking as it was "convening an Open Spaces dialog") is at DevConnections in Vegas on November 6th. Later that week on Friday I'll be doing the ending Keynote at the PNP Summit in Redmond. (Still haven't figure out what to talk about...but I'm getting there.)

Here's my current DevConnections schedule.

This one is an old-ish abstract. We're going to likely split this talk into 30 minutes on Dynamic Data Controls and 30 minutes on MVC, although there's internal rumor of a full 60 minutes on MVC. We shall see.

AMS306: ASP.NET Beyond Visual Studio 2008 and .NET Framework 3.5
Scott Hunter and Scott Hanselman
See some of Microsoft's future plans for enhancing ASP.NET development including better CSS and AJAX integration, the new Dynamic Data Controls, a new Silverlight control, next generation search support, and support for dynamic languages like IronPython and Ruby. Find out how to use these capabilities to make your ASP.NET development even easier.

Eilon is very smart...he's a mastermind behind much of the MVC code you've heard so much about. I suspect this topic and abstract will be changed to be more interesting. We'll probably change it to "Building a Real-World Web Application with Visual Studio 2008 and the .NET Framework v3.5, Part 3 of 2" or "Building a Real-World Web Application: Episode 4" and add Ajax and Silverlight to ScottGu's Part 1 and Part 2 application.

AMS301: Create Great Looking Web Applications Using the New Design and CSS Features in Visual Studio 2008
Eilon Lipton and Scott Hanselman
See how the new Web designer in Visual Studio 2008 makes it easy to build Web applications that are easier to use and more compelling. Find out how Visual Studio 2008 provides the capability to take full advantage of CSS and allows design and development to work seamlessly together in your ASP.NET applications.

For this talk I will likely provide the "jazz hands" to Eilon's most competent code-monkeying.

AMS302: Silverlight for ASP.NET Developers
Eilon Lipton and Scott Hanselman
Microsoft Silverlight is a cross-browser, cross-platform plug-in for delivering the next generation of .NET based media experiences and rich interactive applications for the Web. See how developing Silverlight applications compares to ASP.NET development and how you can integrate Silverlight into your ASP.NET applications today to truly differentiate your web site. See how designers and developers can easily work together using Microsoft Expression to create these great user experiences. In addition you will get a glimpse of the Silverlight 1.1 Alpha, which will allow you to build rich experiences using the managed C# and Visual Basic programming models you are familiar with.

We will do our very best to not suck but we are being thrown in to the pool with both feet tied! ;) Three talks in a day is a lot. I'm happy to paired up in these cases.

UPDATED: We've changed the schedule and I think it'll be a much better show this way. Changes are highlighted. Eilon and I are also doing AMS302 so we're together for three talks!

Time

Room 1

Room 2

10:30 – 11:30

AMS307: Building a Real World Web Application with Visual Studio 2008 and the .NET Framework v3.5, Part I of 3

AMS302: Silverlight for ASP.NET Developers

11:45 – 12:45

AMS308: Building a Real World Web Application with Visual Studio 2008 and the .NET Framework v3.5, Part 2 of 3

AMS306: Developing Data Driven Applications Using ASP.NET Dynamic Data

2:30 – 3:30

AMS303: Internet Information Services 7 for ASP.NET Developers

AMS304: Introduction to the new ASP.NET Model View Controller (MVC) Framework

4:14 – 5:15

AMS301: Building a Real World Web Application with Visual Studio 2008 and the .NET Framework v3.5, Part 3 of 3

AMS305: Displaying Data with the new ListView and DataPager Controls in the .NET Framework 3.5

AMS306: Developing Data Driven Applications Using ASP.NET Dynamic Data
Speaker: Scott Hunter

ASP.NET dynamic data controls are part of a powerful, rich new framework that lets you create data driven ASP.NET applications very easily. It does this by automatically discovering the LINQ data model at runtime and deriving UI behavior from it. A scaffolding framework instantly provides a functional web site for viewing and editing data. This scaffolding can then be easily customized via a template, or by creating standard ASP.NET pages to override the default behavior. At the same time existing applications can easily integrate pieces of the scaffolding logic with their existing pages. In this talk, we will demonstrate how to build rich data driven Web applications from scratch with minimal effort.

AMS304: Introduction to the new ASP.NET Model View Controller (MVC) Framework
Speakers: Scott Hanselman and Eilon Lipton

One of the benefits of using a MVC methodology is that it helps enforce a clean separation of concerns between the models, views and controllers within an application. In the near future, ASP.NET will include support for developing web applications using an MVC based architecture. The MVC pattern can also help enable red/green test driven development (TDD) - where you implement automated unit tests, which define and verify the requirements of new code, first before you actually write the code itself. Join us for a dive into the new MVC Framework and you'll learn how to leverage this new alterative in your own applications.

AMS301: Building a Real World Web Application with Visual Studio 2008 and the .NET Framework v3.5, Part 3 of 3
Speakers: Scott Hanselman and Eilon Lipton

In this session we'll extend the real-world application built in the previous two parts using Visual Studio 2008 and the .NET Framework 3.5. We’ll see how Ajax technology can be cleanly added to an existing codebase to improve the user experience and use less bandwidth without difficulty. Then we’ll add Silverlight to the application to take the user experience to the next level and explore how complementary ASP.NET and Silverlight are and how easy it is to mix HTML and Silverlight seamlessly.

Hope it's good!



Wiring the new house for a Home Network

Posted 2007-10-22 11:01 PM in Musings.

CIMG7356It's official, we're moving! We close tomorrow on a house we've been building. Since it'll be not only our home but also my home office while I work at Microsoft, it needs to be wired as such. It'll be using Verizon Fiber Optic (FIOS) and my Internet connection will be 15mbps downstream and 2mbps upstream.

The pics below are of the "framing" part of the house. For those of you who read this blog who aren't in the US, you may be surprised (or continually surprised) to see our all-wood houses. It's the one thing that we have lots of (so far) here in the US...or at least here in Oregon.

What you're looking at here is the stairs in our living room that head upstairs. The walls haven't been put on in this picture. Under the stairs is my wiring closet. The door is on the far left side there.

CIMG7379 CIMG7380

imageThe picture on the left here shows the piece of cardboard that is soon to be the wiring cabinet. It'll have a clear glass front and a lock. The wiring is all Cat 6 (not Cat 5E) and I'll be mounting a 10/100/1000 Netgear Switch in that cabinet along with a UPS and a wireless router. The switch will also let me route VOIP and RJ11 traffic over ports, so I can re-purpose ports like a small business.

There's 24 RJ45 ports, with each room having at least 2 RJ 45 and 2 Coax. The Office will have at least 10 ports. I just don't trust wireless when I can get hard-drive speed over a hard-wire. So it's Gigabit for me throughout.

Jeff Sandquist's team is going to be doing "Microsoft Cribs." He says "we're honing in on the actual technology people use in their homes." Cool. He's said I can do a video on our setup.

I figure I'll have it all setup by the end of November. Wish me luck! If this is an interesting topic, I'll do a series of posts on the wiring closet, how to save money, how to test for capacity, etc.



In my new ongoing quest to read source code to be a better developer, I now present the ninth in an infinite number of a weekly series called "The Weekly Source Code." Here's some source I'm reading this week that I enjoyed.

Ya, I know this one is just 4 days after the last one, but I was having too much fun and couldn't wait until Wednesday. Plus, it's a new week so poop on you.

Last month Tim Bray shared his experiences writing a program that does, well, here's Joe Cheng's succinct description. Tim calls the project WideFinder.

The Wide Finder challenge is to write a program that:

  1. Scans logfiles for hits on blog articles
  2. which are counted and
  3. sorted with the
  4. top 10 most popular being printed to stdout. It should also
  5. be about as elegant and concise as Tim’s Ruby version and
  6. its performance should scale with additional CPU cores.

And this is done on a fairly large log file of about 250 megs. While Item #6 is the most interesting, many folks are focusing on Item #5. Either way, it's a heck of a lot more interesting problem than FizzBuzz and worth adding to your interview arsenal pocket.

I encourage you to go check out Tim's site as he's continued to list the sources that he finds most interesting. As a primarily C# programmer who's always trying to stretch out of my comfort zone, here's what I've found interesting, in the order I found them interesting.

  • Don Box's Naive Implementation in C# 3.0 - Apparently this is the kind of code Don can write after two beers. Notice the use of yield to make this "LINQ over a text file of CR/LF strings." That's one of those write-it-constantly-over-and-over-again helper methods that makes me wonder why it wasn't just included.
  •     static void Main(string[] args)
        {
            var regex = new Regex(@"GET /ongoing/When/\d\d\dx/(\d\d\d\d/\d\d/\d\d/[^ .]+)");
     
            var grouped = from line in ReadLinesFromFile(@"C:\temp\bray.txt")
                          let match = regex.Match(line)
                          where match.Success
                          let url = match.Value
                          group url by url;
      
            var ordered = from g in grouped
                          let count = g.Count()
                          orderby count descending
                          select new { Count = count, Key = g.Key };
            
            foreach (var item in ordered.Take(10))
                Console.WriteLine("{0}: {1}", item.Count, item.Key);
        }
     
        // LINQ-compatible streaming I/O helper
        public static IEnumerable<string> ReadLinesFromFile(string filename)
        {
            using (StreamReader reader = new StreamReader(filename)) {
                while (true)
                {
                    string s = reader.ReadLine();
                    if (s == null)
                        break;
                    yield return s;
                }
        }
  • Joe Cheng tightens it up with his LINQ skillz and does the group and sort all in one swell foop. As an aside, I'd like to see his QuickTimer class for next week. Nice use of my favorite C# idiom - IDisposable/using. Joe also alludes to some parallelism that could be easily added with PLINQ. Maybe we'll see that code soon.
  • using (new QuickTimer(“Total time”))
    {
        IEnumerable<string> data = new LineReader(args[0]);
    
        Regex regex = new Regex(@”GET /ongoing/When/\d\d\dx/\d\d\d\d/\d\d/\d\d/([^ ]+) “,
            RegexOptions.Compiled | RegexOptions.CultureInvariant);
    
        var result = from line in data
                     let match = regex.Match(line)
                     where match.Success
                     group match by match.Groups[1].Value into grp
                     orderby grp.Count() descending
                     select new { Article = grp.Key, Count = grp.Count() };
    
        foreach (var v in result.Take(10))
            Console.WriteLine(“{0}: {1}”, v.Article, v.Count);
    }
  • My programmer's man-crushes continue as Jomo Fisher posts the WideFinder Naive F# Implementation. Notice how everyone uses "naive" to basically say "I'm sure it could be better, so don't be mean." I can't tell you with a straight face that I totally understand this. It's kind of magical.
  • #light
    open System.Text.RegularExpressions
    open System.IO
    open System.Text
     
    let regex = new Regex(@"GET /ongoing/When/\d\d\dx/(\d\d\d\d/\d\d/\d\d/[^ .]+)", RegexOptions.Compiled)
    
    let seqRead fileName =
        seq { use reader = new StreamReader(File.OpenRead(fileName))
              while not reader.EndOfStream do
                  yield reader.ReadLine() }
    
    let query fileName = 
        seqRead fileName
        |> Seq.map (fun line -> regex.Match(line)) 
        |> Seq.filter (fun regMatch -> regMatch.Success)
        |> Seq.map (fun regMatch -> regMatch.Value)
        |> Seq.countBy (fun url -> url)
    
    *And here's the code to call it:    
    
    for result in query @"file.txt" do 
        let url, count = result
  • Busting out of the Microsoft Languages for a minute, here's Tim's Ruby example:
  • counts = {}
    counts.default = 0
    
    ARGF.each_line do |line|
      if line =~ %r{GET /ongoing/When/\d\d\dx/(\d\d\d\d/\d\d/\d\d/[^ .]+) }
        counts[$1] += 1
      end
    end
    
    keys_by_count = counts.keys.sort { |a, b| counts[b] <=> counts[a] }
    keys_by_count[0 .. 9].each do |key|
      puts "#{counts[key]}: #{key}"
    end
  • Here's the Java version from UnintentionalObjectRetention. I haven't done Java since I worked at Nike in 1997 as a contractor:
  • public class WideFinder {     
      public static void main(String[] args) throws IOException {      
        Map<String, Integer> counts = new HashMap<String, Integer>();      
        Pattern p = Pattern.compile("GET /ongoing/When/\\d\\d\\dx/(\\d\\d\\d\\d/\\d\\d/\\d\\d/[^ .]+) ");  
        BufferedReader in = new BufferedReader(new InputStreamReader(           
             new FileInputStream(args[0]), "US-ASCII"));         
        String line = null;     
        while ((line = in.readLine()) != null) {       
           Matcher m = p.matcher(line);       
           if (m.find()) {            
             String key = m.group();     
             Integer currentCount = counts.get(key);   
             counts.put(key, (currentCount == null ? 1 : (currentCount + 1)));     
           }
        }    
        in.close();      
        List<Entry<String, Integer>> results = new ArrayList<Map.Entry<String, Integer>>(counts.entrySet());      Collections.sort(results, new Comparator<Entry<String, Integer>>() {   
           public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2)        
           {            
              return o2.getValue().compareTo(o1.getValue());     
           }     
         });   
         for(int i = 0; i < 10; i++) {    
           System.out.println(results.get(i));    
         }
      }
    }
  • And last, but kind of first, here it is in LISP from Nate.
  • (defun run (&rest logs)
      (let ((counts (make-hash-table :test #'equal)))
        (dolist (filename logs)
          (with-open-file (stream filename :direction :input
                                  :external-format :latin-1)
            (loop for line = (read-line stream nil stream)
               until (eq line stream)
               do (cl-ppcre:register-groups-bind (match)
                      ("GET /ongoing/When/\\d{3}x/(\\d{4}/\\d{2}/\\d{2}/[^ .]+) " line)
                    (incf (gethash match counts 0))))))
        (loop for key being the hash-keys of counts
           collect key into keys
           finally (map nil #'(lambda (x)
                                (format t "~D: ~A~%" (gethash x counts) x))
                        (subseq (sort keys #'>
                                      :key #'(lambda (x) (gethash x counts))) 0 10)))))

A good way to understand other languages (programming or human) is to read the same story in each of these languages and compare them. Tim's problem serves that purpose well!

Oh, and if you want to see why we program in Managed Code, check out the C version.

Feel free to send me links to cool source that you find hasn't been given a good read.



Where's my Orange Box Royalties?

Posted 2007-10-22 09:07 PM in Musings.

The Half-Life 2 Orange Box is out for the Xbox360 and PC and my buddy Kevin at DiabeTech emailed me this:

"I was image surfing and found this pic. I honestly had to do a double-take as I thought it was you...so, I took a few minutes out and entertained myself by creating one with your likeness.  Just a little Monday morning humor ;)  I call it Hanselraker."

Thanks Kevin! Yikes, that does look like me pre-Laser Eye Surgery. That's not the best pic of me on the left there, but still, might be time to either lose the beard all together and go BabyFace or head the opposite direction and go GrizzlyAdams. Either way, Ryan Reynolds still has my career.

hanselraker

Where's my Half-Life 2 royalties? Fair use my *ss! ;)



Web Common Sense isn't too Common

Posted 2007-10-20 10:22 PM in Musings.

Ah, my poor family. The Web is too complex. I don't mean from a navigational sense, I mean from a navigating your way around it sense.

My mom sent me some emails today asking about scams. Here's one:

"I apologize for continuing to send this stuff, but I do not know what is real and what is junk…is this real?

REMINDER....all cell phone numbers are being released to telemarketing companies tomorrow and you will start to receive sale calls."

Visiting the FTC's website and confirming the SSL Certificate shows that this rumor about Cell Phones in the US and Telemarketers is not true.

But should my Mom have to worry about this kind of thing? Perhaps this is just life in a complex world?

My worry is, what if she asks me for her advice on one of these things and one day I'm wrong? I tell her to suspect everything. I also say that if someone called you at home and said the same thing they're saying in the email, would you believe them? Some how things in text seem more credible than things said out loud.

I know you're the IT Department for your family, Dear Reader. This is our charge and ours to bear happily, but are you also the Web Bullsh*t detector?

How do you protect your friends and family from these things? How do you teach Web Savvy?



logo My eighty-fifth podcast is up. In this one I talk to Matt Davis, an Architect at EarthClassMail.com about their switch from a LAMP stack (Linux, apache, mysql, php/perl/python) to .NET 3.x. What's working, what's not, and what kinds of issues are they are running into as their architect their solution.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

If you have trouble downloading, or your download is slow, do try the torrent with µtorrent or another BitTorrent Downloader.

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Check out their UI Suite of controls for ASP.NET. It's very hardcore stuff. One of the things I appreciate about Telerik is their commitment to completeness. For example, they have a page about their Right-to-Left support while some vendors have zero support, or don't bother testing. They also are committed to XHTML compliance and publish their roadmap. It's nice when your controls vendor is very transparent.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?



Hanselminutes spotted in the wild

Posted 2007-10-19 12:49 AM in Podcast.

This was just too cool not to mention, so forgive me this indulgence. I was over at Moe's Restaurant for lunch a few days ago and this fine gentleman said "Hi Scott" and was, at that moment, listening to Hanselminutes. Amazing coincidence!

hanselminutesphoto2

How cool is that? Are you listening? I think I'll start giving out prizes if this happens again! I should have bought him lunch.

The first time this happened it was in the Chicago Airport bathroom. That was slightly considerably more disturbing, as I was "in the process" at the time. Anyway, so cool that folks enjoy the show.

Keep sending me show ideas!



The Weekly Source Code 8

Posted 2007-10-19 12:04 AM in Source Code.

In my new ongoing quest to read source code to be a better developer, I now present the eighth an infinite number of a weekly series called "The Weekly Source Code." Here's some source I'm reading this week that I enjoyed.

  • The Vista Battery Saver is a fun and simple little application that shuts off Aero and the Sidebar when you're running on batteries. The source is up at CodePlex. He registered his application with Windows for Power Notifications. Windows will send his application a Window Message when the system's power state changes.
  •     //In the main WinForm, he overrides the WndProc
        protected override void WndProc(ref Message m)
        {
             base.WndProc(ref m);
             if (m.Msg == PowerMngr.WM_POWERBROADCAST)
             {
                 PowerMngr.GetManager().PowerSettingChange(m);
             }
        }
    
            //Earlier he selects the messages he's interested in.
            internal void RegisterForPowerNotifications(IntPtr hwnd)
            {
                hPowerSrc = RegisterPowerSettingNotification(hwnd,
                ref GUID_ACDC_POWER_SOURCE,
                DEVICE_NOTIFY_WINDOW_HANDLE);
    
                hBattCapacity = RegisterPowerSettingNotification(hwnd,
                ref GUID_BATTERY_PERCENTAGE_REMAINING,
                DEVICE_NOTIFY_WINDOW_HANDLE);
    
                hMonitorOn = RegisterPowerSettingNotification(hwnd,
                ref GUID_MONITOR_POWER_ON,
                DEVICE_NOTIFY_WINDOW_HANDLE);
    
                hPowerScheme = RegisterPowerSettingNotification(hwnd,
                ref GUID_POWERSCHEME_PERSONALITY,
                DEVICE_NOTIFY_WINDOW_HANDLE);
            }
    
            [DllImport(@"User32", SetLastError = true, EntryPoint = "RegisterPowerSettingNotification", CallingConvention = CallingConvention.StdCall)]
            private static extern IntPtr RegisterPowerSettingNotification(
                IntPtr hRecipient,
                ref Guid PowerSettingGuid,
                Int32 Flags);
  • Patrick Smacchia released a Strongly Typed Path Library today. You know Patrick, he's NDepend-guy and he rocks. He includes a Class Diagram as well:
    PathClassDiagram
    I'll let you go check it out, because you should. I think a class this smart would be a nice addition to the BCL. Here's some of his tests showing the usage of the library. Make careful note of the !'s inside the Asserts. They weren't totally obvious to me. I usually use == false. I find it easier to read.
  •       //
          // Path string validation
          //
          string reason;
          Debug.Assert(PathHelper.IsValidAbsolutePath(@"C:\Dir2\Dir1", out reason));
          Debug.Assert(!PathHelper.IsValidAbsolutePath(@"C:\..\Dir1", out reason));
          Debug.Assert(!PathHelper.IsValidAbsolutePath(@".\Dir1", out reason));
          Debug.Assert(!PathHelper.IsValidAbsolutePath(@"1:\Dir1", out reason));
          Debug.Assert(PathHelper.IsValidRelativePath(@".\Dir1\Dir2", out reason));
          Debug.Assert(PathHelper.IsValidRelativePath(@"..\Dir1\Dir2", out reason));
          Debug.Assert(PathHelper.IsValidRelativePath(@".\Dir1\..\Dir2", out reason));
          Debug.Assert(!PathHelper.IsValidRelativePath(@".\Dir1\..\..\Dir2", out reason));
          Debug.Assert(!PathHelper.IsValidRelativePath(@"C:\Dir1\Dir2", out reason));
  • I was talking to John Lam this week and he said: "BTW I’m having a ton of fun with C# 3.0 – it really is a beautiful language. Here’s an app that I wrote today that dumps all of our implemented Ruby methods to a YAML file." It'll be up on RubyForge later this week, but here's a snippet. It's about 100 lines and it takes a while to sink in. It's simple and it's a nice way to use LINQ against Reflection and the extension methods that use generics is nice and clean. Start at the Main() at the bottom and work your way around. Sure it could be shorter and hackier, but he appears to be balancing functionality with his own sense of aesthetic.
  • using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using Ruby;
    using Ruby.Extensions;
    using Microsoft.Scripting.Utils;
    using Ruby.Runtime;
    
    namespace IronRuby.Library.Scanner {
        static class ExtensionMethods {
            public static IEnumerable<T> SelectCustomAttributes<T>(this Type type) where T : Attribute {
                return type.GetCustomAttributes(typeof(T), false).Cast<T>();
            }
    
            public static IEnumerable<T> SelectCustomAttributes<T>(this MethodInfo method) where T : Attribute {
                return method.GetCustomAttributes(typeof(T), false).Cast<T>();
            }
        }
    
        class RubyClassInfo {
            public Type ClrType { get; set; }
    
            public delegate void Block(IEnumerable<RubyMethodAttribute> methods);
    
            public string Name {
                get { return ClrType.SelectCustomAttributes<RubyClassAttribute>().First().Name ?? ClrType.Name; }
            }
    
            private Type LookupExtensionModuleType(IncludesAttribute attr) {
                Type includedType;
                Program.ExtensionModules.TryGetValue(attr.Type, out includedType);
                return includedType ?? attr.Type;
            }
    
            private void GetMethodNames(Type t, Block accumulate) {
                var methods = (from m in t.GetMethods()
                               where m.IsDefined(typeof(RubyMethodAttribute), false)
                               select m.SelectCustomAttributes<RubyMethodAttribute>().First());
    
                accumulate(methods);
    
                foreach (IncludesAttribute attr in t.SelectCustomAttributes<IncludesAttribute>()) 
                    GetMethodNames(LookupExtensionModuleType(attr), accumulate);
            }
    
            private IEnumerable<string> GetMethodNames(RubyMethodAttributes methodType) {
                var result = new List<string>();
                GetMethodNames(ClrType, methods => 
                    result.AddRange((from m in methods
                                     where m.MethodAttributes == methodType 
                                     select m.Name).Distinct()));
                result.Sort();
                return result;
            }
    
            public IEnumerable<string> InstanceMethods {
                get { return GetMethodNames(RubyMethodAttributes.PublicInstance); }
            }
    
            public IEnumerable<string> SingletonMethods {
                get { return GetMethodNames(RubyMethodAttributes.PublicSingleton); }
            }
        }
    
        class Program {
            static IEnumerable<RubyClassInfo> GetRubyTypes(Assembly a) {
                return from rci in
                            (from t in a.GetTypes()
                             where t.IsDefined(typeof(RubyClassAttribute), false) 
                                   && !t.IsDefined(typeof(RubyExtensionModuleAttribute), false) 
                             select new RubyClassInfo { ClrType = t })
                       orderby rci.Name
                       select rci;
            }
    
            static Dictionary<Type, Type> GetExtensionModules(Assembly a) {
                var modules = from t in a.GetTypes()
                              where t.IsDefined(typeof(RubyExtensionModuleAttribute), false)
                              select new { Type = t, Attribute = t.SelectCustomAttributes<RubyExtensionModuleAttribute>().First() };
                
    
                var result = new Dictionary<Type, Type>();
                foreach(var m in modules)
                    result[m.Attribute.Extends] = m.Type;
                return result;
            }
    
            const string RubyAssembly = @"Ruby, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            internal static Dictionary<Type, Type> ExtensionModules;
    
            static void DumpMethods(IEnumerable<RubyClassInfo> types, Func<RubyClassInfo, IEnumerable<string>> getMethods) {
                foreach (RubyClassInfo rci in types) {
                    Console.WriteLine("{0}:", rci.Name);
                    foreach (string methodName in getMethods(rci))
                        Console.WriteLine("  - {0}", methodName);
                }
            }
    
            static void Main(string[] args) {
                var name = new AssemblyName(RubyAssembly);
                var a = Assembly.Load(name);
    
                ExtensionModules = GetExtensionModules(a);
                var types = GetRubyTypes(a);
    
                DumpMethods(types, t => t.InstanceMethods);
                DumpMethods(types, t => t.SingletonMethods);
            }
        }
    }

Feel free to send me any links to cool source you find.



HTTP Error 404.17 - PHP on IIS7 under 64bit Vista

Posted 2007-10-16 09:27 PM in IIS | Vista | PHP.

IIS 7.0 Detailed Error - 404.17 - Not Found - Windows Internet Explorer If you're getting...

"HTTP Error 404.17 - Not Found - The requested content appears to be script and will not be served by the static file handler."

...on Vista while trying to get PHP working under IIS7 with the standard ISAPI "php5isapi.dll" ask yourself, are you running 64-bit? That ISAPI DLL is a 32-bit DLL, so you'll have to either change your default Application Pool to enable 32-bit, or preferably create a separate 32-bit AppPool for your PHP Application.

Right click on the Application Pool and select "Advanced Settings" then "Enable 32-bit Applications."

Advanced Settings

At this point, you're all set with the standard ISAPI PHP stuff. 

phpinfo() - Windows Internet Explorer

Even better, consider using the FastCGI for IIS component. I'll do a screencast on that soon.



SkittlesFiveSecondRule There's a good article in the Washington Post from July that was on a repeat on the Radio this morning about the Five Second Rule. There's even some research on it and a WikiWorld comic.

"The five-second rule. If you've never heard of it, ask any sixth-grader. "It means that if you drop something on the ground, you can still eat it if you pick it up in five seconds," says Kiara Hopkins, 11."

I'm not sure when this started, but I've always known this. I think my two-year-old knows this, although it may be the five-day-rule for him. 

"It's not just for children: In a 2003 survey conducted at the University of Illinois, 70 percent of women and 56 percent of men had knowledge of the rule."

I'm shocked it's not 100%. There's also the interesting "Line of Sight Corollary to the Five Second Rule" which allows you to extend the Five Second Rule as long as you held the dropped object in your line of sight the entire time. "Who knows what could have happened while I wasn't looking?"

Additionally, things like M&Ms and Skittles candies have a hard-shell or 'armor' that allow for an more liberal interpretation of the Rule. Wet things, on the other hand, like cake or fruit, might only be allowed two seconds, or none at all.

Because I have a fairly international (non-US) bunch of readers here, I'd like to ask you:

  • Dear International Reader, is the Five Second Rule a global (read: all humans) phenomenon? Does it cross cultures?
  • More interestingly, what do you call it in your native language?

Discuss.



When you install .NET 3.5 on your system, while the .NET CLR is the same and runs the same, there's some additional Properties and Methods that were added to the Base Class Libraries in order to make some 3.5 features like LINQ work as well as fix a few customer issues.

Daniel Moth has a very nice diagram explaining what "RedBits" and "GreenBits" mean.

"When we say red bits, those are Framework bits that exist in RTM today i.e. NetFx v2.0 and NetFx v3.0...When we say green bits, we mean brand new assemblies with brand new types in them. These are simply adding to the .NET Framework (not changing or removing) just like Fx 3.0 was simply adding to v2.0 without changing existing assemblies and without changing the CLR engine."

Krzysztof has a blog post about these new (kinda obscure) APIs and fortunately a nice FxCop Rule you can drop into your C:\Program Files\Microsoft Visual Studio 9.0\Team Tools\Static Analysis Tools\FxCop\Rules folder and you'll get a nice warning if you bump into one of these APIs. To be clear, they are not something you'll bump into in your regular life, but it's possible. Dan Moseley blogged about this from the MSBUILD point of view.

The situation you might get into would be that you'd develop on a Visual Studoi 2008 system with .NET 3.5 and targeted .NE T Framework 2.0 (but you have 2.0 SP1 with these new 2.0 methods), then you deploy to an older system that has only .NET 2.0 RTM (not Service Pack'ed). At this point you might get a MethodMissingException because that older system might not have the new method or property. Of course, you could just install the latest 2.0, but if you don't want to, then don't use the new methods/types/properties. Hence the optional FxCop Rule.

1473897382_374fc28d10_o

Krzysztof send me a text file with the list of new Properties and Methods and I wrote a little program to generate an HTML file that shows the additions (many are new overloads) and links them to MSDN help. I couldn't get to the exact method overloads so do make sure the parameters line up when you're reading the help.

http://www.hanselman.com/blog/content/binary/RedBitsChangesv2.html

NOTE: This is a different list from the original diff I did between 3.5 and 2.0. The original list was the differences between all of 2.0 and 3.5 and this list is JUST the BCL. Just the core.



Patrick Cauldwell has a good list of Programming Guiding Principles he calls This I Believe: The Developer Edition. I've blogged about them before.

I got an email today that went something like this:

I have an interface called IStorageConnection and one of its methods is Save(...). The storage connection object available to user is configured through configuration files. The storage could be either the FileSystem or the Database. In that case, how is the consumer of the IstorageConnection interface going to know that exceptions to expect? If using the FileSystem, you can expect an IOException. If using the Database, you can expect a SQLException. Given this case, how can the customer get away from handling the base Exception and only handle specific exceptions. Also, keep in mind that other storage connections objects can be deployed and plugged into the system in the future.

This reminded me of a favorite rule of Patrick's that use a lot as well.

Simply stated, we say "If your method can't do what it's name promises it can, throw."

If your method is called "Save" and it can't Save, then throw. If it's called DoSomething and it can't DoSomething, throw. The idea is that the method name is a verb and a contract. It's promising to do its best and if it can't do it, it's very likely exceptional.

In this gentleman's example, I figure if you've got a pluggable storage interface underneath, I'd suggest creating a generic "StorageException," and put the actual exception in the InnerException property. However, the point is that it didn't work. Whether the consumer of the Exception cares more than that is a secondary issue.

What are your rules for when to throw and Exception? And please, don't say Exceptions are evil and that HResults should rule the day. Surely the Great .NET Exception Panic of 2001 is over, right? ;)



Retrospective: Halo 3 Fights Diabetes

Posted 2007-10-12 10:32 PM in Diabetes | Gaming.

It was epic. Truly epic. Thfe stuff you tell, if not your grandchildren, your middle-aged nerdy neighbor about. We had a great time at Cinetopia and raised a lot of money for the American Diabetes Association.

You can make a tax-deductible donation today!

Big Thanks to Everyone involved:

  • Jason Mauer and Microsoft Portland for the Xboxes, the Halo 3 games, organization, logistics and his tireless work and two 42" plasmas.
  • Rich Claussen for all things business, negotiations, and convincing Cinetopia we had a good idea.
  • Greg Hughes for his press-contacting expertise and for spreading the word in creative ways in the Oregonian, the Willamette Week and on KXL radio.
  • The SAO for their sponsorship and for all their help the evening of the event!
  • John Poore, Michael Willits, Jennifer Bernstein and everyone at Robert Half Technology for their sponsorship and their commitment to the community!
  • Wendy Fatz and Rodger DeGeorge from CompView for believing in the dream and loaning us two projectors.
  • Lee Williamson and PADNUG for the Food and Drinks!
  • Aivea for their sponsorship and generous donation!
  • Rudyard and the team at Cinetopia, a locally-owned rockin' sweet luxury theatre, for shutting down 2 of their 8 Super-HD screens!

And lastly, to everyone who donated and everyone who was powned or dispensed pownage all evening long!

CIMG7547 CIMG7542 

CIMG7523 CIMG7519 

CIMG7518 CIMG7517

CIMG7516 CIMG7511

Let's do it again soon!



image My eighty-fourth podcast is up. Scott chats on the Microsoft campus with Stephen Toub, a Microsoft Developer working on a team coming up with new ways to make concurrency programming easier with .NET. We get pretty deep and pretty philosophical about concurrency, threading, and parallelism. Also check out an older Channel 9 Video (just released) on the topic as well.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

If you have trouble downloading, or your download is slow, do try the torrent with µtorrent or another BitTorrent Downloader.

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Check out their UI Suite of controls for ASP.NET. It's very hardcore stuff. One of the things I appreciate about Telerik is their commitment to completeness. For example, they have a page about their Right-to-Left support while some vendors have zero support, or don't bother testing. They also are committed to XHTML compliance and publish their roadmap. It's nice when your controls vendor is very transparent.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?



The Weekly Source Code 7

Posted 2007-10-11 03:44 PM in ASP.NET | Learning .NET | Programming | Source Code.

In my new ongoing quest to read source code to be a better developer, I now present the seventh in an infinite number of a weekly series called "The Weekly Source Code." Here's some source I'm reading this week that I enjoyed.

I got a little sidetracked the recent trip to the ALT.NET conference, so forgive me for missing last week.

  • Joe Cheng's Schwartzian Transform in C# 3.0 - Whenever someone knows the official name for technique, be it in chess or in code, they're usually smarter than I. "You are using Bonetti's Defense against me, ah?" Joe is one of those guys. ;)
    "What’s a Schwartzian Transform? It’s a way of efficiently sorting a list of objects according to some potentially expensive-to-calculate property of those objects. For example, let’s say you have an array of filenames, and you want to sort them by their last modified dates"
    This is a very useful technique to know and nice and clean in C# 3.0.
  • public static List<TElement> SortBy2<TElement, TSortBy>(
            this List<TElement> coll,
            Converter<TElement, TSortBy> converter,
            Comparison<TSortBy> comparison)
        {
            return coll
                .ConvertAll(el => new { Key = converter(el), Value = el })
                .Sort((a, b) => comparison(a.Key, b.Key))
                .ConvertAll(x => x.Value);
        }
  • LINQ to Amazon - This is a little old, but it's still darn interesting to read. If you've been thinking about implementing LINQ over an object or web service that your company has, this is a good place to start. I'll let you go digging around, but here's some bits I found interesting. Note also that the code is very old and I haven't been able to find the latest stuff.
    This is what I call Left-Hand/Right-Hand code where we're pulling with one hand, in this case XML and handing off with the other hand, in this case, making a LINQ List.  It tends to be very tedious but LINQ sure makes it easy.
  • XNamespace ns = NAMESPACE_AWSECommerceService; 
    var books = from book in booksDoc.Descendants(ns+"Item") 
        select new Book { 
            Title = book.Element(ns+"ItemAttributes").Element(ns+"Title").Value, 
                                Publisher = book.Element(ns+"ItemAttributes").Element(ns+"Publisher").Value, 
                                Year = uint.Parse(((String)book.Element(ns+"ItemAttributes").Element(ns+"PublicationDate").Value).Substring(0, 4)), 
                                Authors = ( from author in book.Descendants(ns+"Author") 
            select (String) author.Value ).ToList() 
    };
  • Argotic Syndication Framework - Woof, a full implementation of Atom 1.0, OPML 2.0, RSD 1.0, and RSS 2.0 syndication formats. If you're looking for syndication source look no further. This is not only very clean code that's also well organized with a very interesting extension mechanism for including other namespaces within your syndication format.  It's also excessively well documented. I hate them. ;) Although, I'm not sure where the tests are, it's pretty clear that this reflects a huge amount of work.  Or a lot of code generation.
    There is far too much to paste much here, but what are the things I click away was a new attribute but I hadn't heard of yet. You can tell FxCop to relax as they do here with a naming rule.
  • [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rss")]
    public class RssFeedCreatedEventArgs : EventArgs, IComparable {...
  • LukeH and a fully LINQified RayTracer - Seriously, someone give this guy some money or a warm handshake or something. This is unreal...it's single line of LINQ. That means it's one expression. Luke is a glutton for punishment because I'm still trying to get my brain around the statement. This guy is a beast. I'm thinking of starting a cult around him. Here's his code, but go read his post for the explanation. Go! Right now! I'll wait here.
  • var pixelsQuery =
        from y in Enumerable.Range(0, screenHeight)
        let recenterY = -(y - (screenHeight / 2.0)) / (2.0 * screenHeight)
        select from x in Enumerable.Range(0, screenWidth)
               let recenterX = (x - (screenWidth / 2.0)) / (2.0 * screenWidth)
               let point = Vector.Norm(Vector.Plus(scene.Camera.Forward,                                                Vector.Plus(Vector.Times(recenterX, scene.Camera.Right),
                                                               Vector.Times(recenterY, scene.Camera.Up))))
               let ray = new Ray { Start = scene.Camera.Pos, Dir = point }
               let computeTraceRay = (Func<Func<TraceRayArgs, Color>, Func<TraceRayArgs, Color>>)
                (f => traceRayArgs =>
                 (from isect in
                      from thing in traceRayArgs.Scene.Things
                      select thing.Intersect(traceRayArgs.Ray)
                  where isect != null
                  orderby isect.Dist
                  let d = isect.Ray.Dir
                  let pos = Vector.Plus(Vector.Times(isect.Dist, isect.Ray.Dir), isect.Ray.Start)
                  let normal = isect.Thing.Normal(pos)
                  let reflectDir = Vector.Minus(d, Vector.Times(2 * Vector.Dot(normal, d), normal))
                  let naturalColors =                   from light in traceRayArgs.Scene.Lights
                      let ldis = Vector.Minus(light.Pos, pos)
                      let livec = Vector.Norm(ldis)
                      let testRay = new Ray { Start = pos, Dir = livec }
                      let testIsects = from inter in
                                           from thing in traceRayArgs.Scene.Things
                                           select thing.Intersect(testRay)
                                       where inter != null
                                       orderby inter.Dist
                                       select inter
                      let testIsect = testIsects.FirstOrDefault()
                      let neatIsect = testIsect == null ? 0 : testIsect.Dist
                      let isInShadow = !((neatIsect > Vector.Mag(ldis)) || (neatIsect == 0))
                      where !isInShadow
                      let illum = Vector.Dot(livec, normal)
                      let lcolor = illum > 0 ? Color.Times(illum, light.Color) : Color.Make(0, 0, 0)
                      let specular = Vector.Dot(livec, Vector.Norm(reflectDir))
                      let scolor = specular > 0 
                                   ? Color.Times(Math.Pow(specular, isect.Thing.Surface.Roughness), light.Color) 
                                   : Color.Make(0, 0, 0)
                      select Color.Plus(Color.Times(isect.Thing.Surface.Diffuse(pos), lcolor),
                                        Color.Times(isect.Thing.Surface.Specular(pos), scolor))
                  let reflectPos = Vector.Plus(pos, Vector.Times(.001, reflectDir))
                  let reflectColor =                   traceRayArgs.Depth >= MaxDepth
                      ? Color.Make(.5, .5, .5)
                      : Color.Times(isect.Thing.Surface.Reflect(reflectPos), 
                                    f(new TraceRayArgs(new Ray { Start = reflectPos, Dir = reflectDir }, 
                                                       traceRayArgs.Scene,                                                    traceRayArgs.Depth + 1)))
                  select naturalColors.Aggregate(reflectColor, (color, natColor) => Color.Plus(color, natColor)))                                  .DefaultIfEmpty(Color.Background).First())
               let traceRay = Y(computeTraceRay)
               select new { X = x, Y = y, Color = traceRay(new TraceRayArgs(ray, scene, 0)) };
    
    foreach (var row in pixelsQuery)
        foreach (var pixel in row)
            setPixel(pixel.X, pixel.Y, pixel.Color.ToDrawingColor());

Feel free to send me links to cool source that you find hasn't been given a good read.



ScottHaOnDLRandMVCatALTNET

I attended the ALT.NET Conference last weekend in Austin, TX. I personally find the name "Alt" as in "Alternative" too polarizing and prefer terms like "Pragmatic.NET" or "Agile.NET." At the conference I suggested, partially in jest, that we call it "NIH.NET" as in "Not Invented Here.NET." ;)

Ultimately this is a group that believes in:

  • Continuous Learning
  • Being Open to Open Source Solutions
  • Challenging the Status Quo
  • Good Software Practices
  • DRY (Don't Repeat Yourself)
  • Common Sense when possible

I asked "Why is this alternative," and Martin Fowler echoed those sentiments. When I was at Corillian we were using NAnt, NUnit, Subversion, NCover, NDoc, NDepend, CruiseControl, Watir/Watin and Ruby and we practiced Scrum with an Agile Coach. Did that make us alternative or were we just getting the job done? We made practical and pragmatic decisions and it worked out OK.

Whether this is Alternative .NET or just Practical .NET, it's a conversation and that's a a good thing.

ScottGuOnMVCatALTNETScottGu gave an hour long presentation on the upcoming MVC Framework and I took some guerilla video. ScottGu's presentation is here in Silverlight and it's about 60 minutes long. Considering it's so long, the video squished nicely.

This was the first time the MVC Framework was shown publicly.  Note that this was a Prototype, not the Production code and both ScottGu and I make that point a number of times to drive home that it's early. Some of the code was written on a plane, just to give you an idea.

After The Gu did his piece on the MVC Framework, I showed some prototype hacking that I'd done over the previous few days along with some work Phil Haack did. My presentation is here as Silverlight and it's about 30 minutes long. I showed the Model View Controller with Controllers in IronPython and an IronPython view using a WebFormViewEngine. Then I talked about the possibilities of alternate ViewEngines and showed Phil Haack's prototype RubyViewEngine.

Both talks show lots of code. Of course, this is prototype madness. No warranty, express or implied. Features come and go, but I hope this shows that we're committed to aiming for as much awesomeness as is humanly possible. I hope you enjoy them, even though my webcam hand was shaky after an hour. I used a new Microsoft NX-7000 Lifecam for the recoding - it's a great camera for the Alpha Geek. ;)

Here's the videos I promised:

If you want to link to these, link to this post, not those links, as the videos might move around. Thanks.

Here's some of the buzz around the new Framework. I hope this framework is a harbinger of things to come in future frameworks.

Things are looking up.



Just a reminder if you're in Portland or SW Washington that now is the time to register for the Halo at Cinetopia for Diabetes Party. You need to pre-register and please, do tell your friends and family! Let's fill it up!

WHAT

We're renting out TWO SUPER HIGH DEF (2048p) 50 foot Movie Theaters and playing Halo. There will be soda and popcorn and pownage. Eighteen and older please.

WHERE

The Glory and Wonder that is Cinetopia just over the bridge in Vancouver.

WHEN

The event is this Thursday, October 11th from 7pm to Midnight.

HOW

Your donation of $25 or more at the door will go straight to the America Diabetes Association. You can also pre-donate and bring your printed receipt to the door. We have room for only 120 people so register today!

Register for this event at http://iammasterchief.com/ with the RSVP code "FIGHTDIABETES". The event is Thursday, October 11th from 7pm to Midnight.

Note that the banner in the upper left of the reservation site does mention the “PRELAUNCH PARTY 09 24 07” even though the center box shows “10/11/07 – Cinetopia”. Just make sure to use the right RSVP code.

WHY

Because it's Halo. And to Fight Diabetes.

We'll see you there!



I really like the new LINQ to XML direct language support in VB9. However, while it's cool, I'm not ready (or willing) to dump C# and start using VB. But, if I could only use VB9 just for the XML stuff...

Sure, I could create a VB assembly and a C# assembly and add them to a solution, but then I'd have two assemblies. I could add a PostBuildEvent batch file and call ILMerge myself (merging the two assemblies into one), but that just doesn't seem pure enough.

solutionWhat I really want is to be able to mark an assembly as merge-able and have it automatically merged in just because it's referenced.

Here's what I came up with. Thanks to Dan Moseley and Joshua Flanagan for their help. Thanks to Jomo Fisher for the Target File.

First, here's the sample project. There's a C# MergeConsole.exe that references a C# MainLibraryILMerge.dll that references a VB XmlStuffLibrary.

If I compile it as it is, I get a folder structure that includes three resulting assemblies.

folder1

Now, here's were we start messing around. Remember, we don't want to have the extra VB-specific XmlStuffLibrary right? We just want to use the XML features.

First, download and install ILMerge in the standard location.

Now, go to C:\Program Files\MSBuild (or C:\Program Files (x86)\MSBuild on x64) and make a new text file called "Ilmerge.CSharp.targets". This file is the start of a hack we're going to borrow from Jomo Fisher.

Note the red bits in the file below. We're creating an "AfterBuild" target...a Post Build Event in the MSBUILD world.

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> 
    
  <Target Name="AfterBuild">
    <CreateItem Include="@(ReferencePath)" Condition="'%(CopyLocal)'=='true' and '%(ReferencePath.IlMerge)'=='true'">
      <Output TaskParameter="Include" ItemName="IlmergeAssemblies"/>
    </CreateItem>
    <Message Text="MERGING: @(IlmergeAssemblies->'%(Filename)')" Importance="High" />
    <Exec Command="&quot;$(ProgramFiles)\Microsoft\Ilmerge\Ilmerge.exe&quot; /out:@(MainAssembly) &quot;@(IntermediateAssembly)&quot; @(IlmergeAssemblies->'&quot;%(FullPath)&quot;', ' ')" />
  </Target>
  <Target Name="_CopyFilesMarkedCopyLocal"/>
</Project>

In this target, we're going to look for assemblies that are marked CopyLocal but also that have IlMerge equal to true. Then we'll call IlMerge passing in those referenced assemblies.

Is this some undocumented MSBUILD thing? No, you can put whatever you want in an MSBUILD file and refer to it later. Since CSPROJ files (Visual Studio Projects) are MSBUILD files, we can open it in Notepad.

Open the CSPROJ for the C# project that references the VB one and make these changes: 

... 
<ItemGroup>
   <ProjectReference Include="..\XmlStuffLibrary\XmlStuffLibrary.vbproj">  
    <Project>{someguid}</Project>    
    <Name>XmlStuffLibrary</Name>
    <Private>True</Private>
    <IlMerge>True</IlMerge>
  </ProjectReference>
</ItemGroup>  
<Import Project="$(MSBuildExtensionsPath)\Ilmerge.CSharp.targets" />
<!-- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> -->
...

At the bottom there, we're commenting out Microsoft.CSharp.targets (but notice that it's included back in at the top of the new  Ilmerge.CSharp.targets.

Then a totally made-up element <IlMerge> is added. That's the most important part. We're saying we want this specific Reference (or References) merged into the final assembly. This made-up element is referenced in the conditional "'%(ReferencePath.IlMerge)" above in the AfterBuild.

The addition of this IlMerge element to Jomo's original hack gives me the flexibility to pick which references I want to merge in, and in my specific case, I'll use the VB9 new XML hotness inside my C# assemblies. Schwing.

Close and save. If you're running Visual Studio, switch back there and it'll prompt you to Reload your project file.Because we've messed it it, you'll get this warning dialog. Select "Load project normally" and click OK.

Security Warning for MainLibraryILMerge

At this point we can build either from the command-line using MSBUILD on the Solution (SLN) file, but more importantly we can (of course) build from inside Visual Studio.

MergeConsole - Microsoft Visual Studio

You can see the output in the Output Window in VS.NET.

MERGING: XmlStuffLibrary
"C:\Program Files (x86)\Microsoft\Ilmerge\Ilmerge.exe"
  /out:bin\Debug\MainLibrary.dll "obj\Debug\MainLibrary.dll"   
  "C:\dev\CSharpVBTogetherAtLast\MergeConsole\XmlStuffLibrary
  \bin\Debug\XmlStuffLibrary.dll"

And the results in the bin folder:

folder2

Looks like the VB XmlStuffLibrary is gone! But where it is? Let's load up MainLibrary in Reflector:

reflector1

Looks like they are both in there. To refresh, if I want to merge in VB assemblies:

  • Change the referencing CSPROJ to import "IlMerge.CSharp.targets"
  • Add <IlMerge>True</IlMerge> to the references you want merged in.
  • Save, Reload, Build

C# and VB, living together, mass hysteria!



The Red Ring of Death makes itself known

Posted 2007-10-04 10:53 AM in Gaming.

CIMG7489Crap. Now what?

I wish I know exactly what causes/caused this.

Last night Mo said the Xbox locked up hard while she was listening to her Zune. She thought she broke it. Reboot and we were fine.

Later, I wasn't able to connect to the Windows Home Server to stream pictures. Reboot and the Xbox locked up while in the "splash screen" presentation.

Smells like heat. I unplugged everything and plugged it back in again and it's working fine. Haven't had a problem since.

However, this was the FIRST and only time I ever had any trouble with the thing. It's a "launch day" Xbox360 with the add-on 120gig drive. I'm wondering if I should send it in for a replacement or just get an HDMI-enabled 1080p model.

Sigh.



2swan-asa3 Yes, you read that correctly. Microsoft is releasing the source code to a bunch of .NET Framework Libraries under the "Microsoft Reference License." This means you can view the source for reference, but not for recompilation, etc.

This is a lot like Symbol Servers, which I've talked about on the blog before, but this'll be a "Public Source Server" (Source Servers are an old concept, but rare to see in the wild) so that you be a able to debug seamlessly between your code and the Framework's code.

In my first "scoop" in my new job at Microsoft, I've already got a show ready for you, recorded last week! See, I told you I'd take care of you. 

This show is actually an interview with Shawn Burke the mastermind behind this move who posted his intent to make this happen on his personal blog in 2005! His current job is being in charge of the Ajax Toolkit, but he's been working on this source code release idea for years - plural.

Support for this new public Microsoft .NET Source Server feature will be in Visual Studio 2008 when it comes out later this year. It'll be a simple setup process and you'll be on your way to "Stepping Into" the code.

We talk on the podcast about the differences between using Reflector to look at source and looking at the source itself. We ask Shawn about Source Servers vs. Symbol Servers, and how Microsoft is going to size their network to support the demand.

dlprocess_thumb

As soon as I have details on how this configuration process will work, I'll let you know. I suspect it'll be very similar to the way Symbol and Source Servers work today in Visual Studio.

Enjoy!



fireboss Microsoft appears to run on Outlook and Exchange. Seems like an obvious statement as many places run on Outlook and Exchange. But I'm saying it with emphasis. These guys used Outlook like it's an IM client. There's also a distribution list for everything.

New job, new fresh email box, time to get organized and serious about ZEB (Zero Email Bounce.) You can't really get your Inbox to zero and stay there but you can "bounce" against zero, which I do a few times a day. If it's in your inbox it's not been processed.

I used a number of techniques and features in Outlook to make my life (theoretically) easier:

Folders

outlookfolders[1]I use a "Getting Things Done" style of organization. I've got my folders laid out like this.

I've got Outlook Rules for the Various Mailing Lists I've gotten myself on in the last few weeks. That's the other other "Inboxes" are for.

The "Inbox - CC" folder is for when I'm cc'ed on an email. The actual Inbox itself is only for when an email is sent directly to me. Everything else goes somewhere else.

The Action folders start with an @ sign and are at the top.

  • There's things that require @Action that aren't projects.
  • Topics to @Blog about
  • People to see and things to do on my @Next Redmond Trip.
  • Emails I need to @Reply to that will take longer than 5 minutes to respond.
  • There's things I'll do @Someday soon, but just not now.
  • Things I'm @Snooze-ing on, but I'm not willing to move them completely out of mind.
  • Finally there's things I'm @Waiting For other people do to for me.
  • The Conversation History folder is where internal Instant Message conversations go. This is REALLY useful for reference. Missed IMs appear in the Inbox and are filed as needed.

Anything that comes into the inbox needs to be processed and one of the following GTD things needs to happen:

  • Do It
  • Drop It
  • Defer It
  • Delegate It

Then there's the Projects folder. These are long-running (more than a few days) projects that I'm actively working on. Emails that are important to those Projects go in those folders. It's pretty minimal reference stuff.

The Reference folder is just that, it's Reference stuff. Things I'll want to search for later, and under it is the IT Issues folder which is also for reference, but specific to IT stuff I'm suffering with working through.

When my inbox is at zero I do a quick sweep through my @ folders before continuing work on a Project.

Calendars

I really like Outlook 2007's calendaring and it grows on me more and more. I use colors to categories my appointments, but I also use multiple calendars more and more using the ICS Webcal standard. I've got four different calendars in addition to my standard calendar.

  • One is fed from TripIt.com - I'll blog about them later, but they're freaking brilliant.
  • One is the feed from my wife's Google Calendar (this is also fantastic)
  • One is fed from my wife and my Project at BaseCamp. We're building a house and we're managing the project, the move and appointments with many subcontractors via this tool and I'm subscribed to the Milestones in Outlook, and she in Google Calendar.
  • One is from my publisher something we're working on.

Note that the tabs are next to each other near the top (under where it says "October 2007"). This way, rather than split-screen, each calendar is transparently overlaid over the other. I've found this to be a REALLY effective way of visualizing up to six different calendars while keeping each one separate.

cal[1]

If you're not using this feature, I'd encourage you to check it out.

The last thing I've done to make it easier for external folks to schedule meetings with me is I've made a redirect from http://www.hanselman.com/freebusy to my published Free/Busy information. This can be done by right-clicking on your calendar and publishing just the free/busy information to the Internet. I just made a single default.aspx file to rediect to the ultimate URL. This makes scheduling meetings with folks outside Microsoft just that much easier.

Mobile

s620_141x228 Last and least, I've got a Windows Mobile phone and it's hooked up to Exchange and I've made the (difficult) conscious decision to only sync the "Inbox" and the "Inbox - CC" Folders to the device.

The thinking being that there's little that's totally crucial that could happen on a Mailing List (as I don't yet own any) that would require my immediate and mobile attention.

This system has worked for me so far - three-plus weeks. We'll see if it holds up under the weight of the unknown future.

I'd be interested to see if there's anything in this system that you find either interesting/compelling or totally lame. You and your 6000 inbox emails. You freak. ;)

P.S. The fire hose child is not my son.

Update: The flickr member who took the Fire House photo asked me to take it down. I replaced it with another. Bummer. Fair-use and copy-right is a confusing thing.