Scott Hanselman

How to Programmatically Detect if an Assembly is Compiled in Debug or Release mode

August 30, '06 Comments [12] Posted in Programming
Sponsored By

Nagaraj from my company made this little util recently to run against a compiled assembly and see if it is a Debug or Release version. I added the DOS ErrorLevel return codes.

using System;

using System.IO;

using System.Diagnostics;

using System.Reflection;

 

namespace Foo.Tools

{

    class BuildFind

    {

        public static int GetBuildType(string AssemblyName)

        {

            Assembly assm = Assembly.LoadFrom(AssemblyName);

            object[] attributes = assm.GetCustomAttributes(typeof(DebuggableAttribute), false);

 

            if (attributes.Length == 0)

            {

                Console.WriteLine(String.Format("{0} is a RELEASE Build....", AssemblyName));

                return 0;

            }

            foreach (Attribute attr in attributes)

            {

                if (attr is DebuggableAttribute)

                {

                    DebuggableAttribute d = attr as DebuggableAttribute;

                    Console.WriteLine(
                       String.Format("Run time Optimizer is enabled : {0}", !d.IsJITOptimizerDisabled));

                    Console.WriteLine(
                        String.Format("Run time Tracking is enabled : {0}", d.IsJITTrackingEnabled));

                    if (d.IsJITOptimizerDisabled == true)

                    {

                        Console.WriteLine(String.Format("{0} is a DEBUG Build....", AssemblyName));

                        return 1;

                    }

                    else

                    {

                        Console.WriteLine(String.Format("{0} is a RELEASE Build....", AssemblyName));

                        return 0;

                    }

                }

            }

            return 3;

        }

 

        [STAThread]

        static int Main(string[] args)

        {

            if (args.Length == 0)

            {

                Console.WriteLine("Usage GetBuildType <assemblyName>");

                return 2;

            }

            return BuildFind.GetBuildType(args[0]);

        }

    }

}

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

SOLVED: How to Force IIS to load a certain version of the .NET CLR

August 30, '06 Comments [4] Posted in ASP.NET | HttpModule | Web Services
Sponsored By

Micky McQuade turned me on to some code (from MSPSS) to solve my How to FORCE IIS to load a certain version of the CLR/.NET Framework. Greg Menounos also mentioned this solution in the comments.

PROBLEM: As discussed before, you can't use requiredRuntime or any .config changes (any that you ought to) to influence what version of the .NET Framework gets loaded into the IIS worker process. If you are using a .NET object as a COM object within Classic ASP, you'll always get the very latest .NET Framework installed on the machine. The values associated with the (fake) COM Object in the Registry are ignored. NOTE, this problem in with IIS/ASP/ASP.NET. If you're doing other things like calling .NET objects from VB6 Clients or something like that, you can always create a .exe.config and influence things with requiredRuntime like I talked about here.

SOLUTION: The solution is a clever hack. What's the first opportunity to "jump in" and affect IIS? When the ISAPI Filters are loaded. Which ISAPI Filter method is called only once? Why GetFilterVersion(), in fact.

This is one of those 'slap your forehead' solutions because it makes sense when you hear it, but it sounds SO tedious when you come up with it and have to actually sully your nails with C++ again. Sigh, I coded in C++ for 8 years and now not only have I forgotten my ninja skills but I feel slightly dirty when I'm back in there. 

DISCLAIMER: This code of course assumes that there isn't some other higher-priority ISAPI filter doing crazy stuff in .NET. Unlikely, but worth mentioning. It's also totally unsupported, and you didn't get it here. In fact, you don't know where you got it. Who is this? What are you doing here? Move along, nothing to see here! No warranty expressed or implied as I didn't write it. Don't bug Micky or ask MS about it.  There's also no guarantee that this, or anything like this, is a solution for your problem(s).

But it's interesting to read.

BOOL CNativeISAPIFilter::GetFilterVersion(PHTTP_FILTER_VERSION pVer)
{

    LPWSTR pszVer = L"v1.1.4322";

    //or "svr" if you're on a multiproc box and you want the server GC in this process.

    LPWSTR pszFlavor = L"wks";

    ICorRuntimeHost *pHost = NULL;

 

    HRESULT hr = CorBindToRuntimeEx(

        //version

        pszVer,

        // svr or wks

        pszFlavor,

        //domain-neutral"ness" and gc settings - see below.

        STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | STARTUP_CONCURRENT_GC,

            CLSID_CorRuntimeHost,

        IID_ICorRuntimeHost,

        (void **)&pHost);

 

    // Call default implementation for initialization

    CHttpFilter::GetFilterVersion(pVer);

 

    // Clear the flags set by base class

    pVer->dwFlags &= ~SF_NOTIFY_ORDER_MASK;

 

    // Set the flags we are interested in

    pVer->dwFlags |= SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT |
          SF_NOTIFY_END_OF_NET_SESSION | SF_NOTIFY_END_OF_REQUEST;

 

    // Set Priority

    pVer->dwFlags |= SF_NOTIFY_ORDER_HIGH;

 

    // Load description string

    TCHAR sz[SF_MAX_FILTER_DESC_LEN+1];

 

    ISAPIVERIFY(::LoadString(AfxGetResourceHandle(),

    IDS_FILTER, sz, SF_MAX_FILTER_DESC_LEN));

    _tcscpy(pVer->lpszFilterDesc, sz);

 

    return TRUE;

}

File Attachment: NativeISAPI.zip (558 KB)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Good Exception Management Rules of Thumb

August 30, '06 Comments [13] Posted in ASP.NET | Learning .NET
Sponsored By

I was coming up with Good Exception Management Rules of Thumb for .NET. Here's what my brainstorming came up with. What do you have as good Rules o' Thumb?

  • Exceptions are exceptional and should be treated as such. If something exceptional, unusual, or generally "not supposed to ordinarily happen" then an exception is a reasonable thing to do.
    • You shouldn't throw exceptions for things that happen all the time. Then they'd be "ordinaries".
  • If your functions are named well, using verbs (actions) and nouns (stuff to take action on) then throw an exception if your method can't do what it says it can.
    • For example, SaveBook(). If it can't save the book - it can't do what it promised - then throw an exception. That might be for a number of reasons.
  • If you can, throw an exception that means something, and if there's an exception that already exists that matches what happened semantically, throw that.
    • Don't create a HanselmanException just because you're writing the Hanselman module unless you're adding data or valuable semantics to the type.
      If you are building a framework (or even if you're not) throw ArgumentExceptions and ArgumentNullExceptions liberally. Just as your method should throw if it can't do what it promised, it should throw if you supplied it with crap input.
  • If something horrible happens (something exceptional) then you need to decide if you can keep going.
    • Don't catch exceptions you can't do anything about. It's likely if you could do something about it, it wouldn't be exceptional, and you might consider calling TryParse, or File.Exists, or whatever it takes to prevent that exception.
  • There are reasons to swallow exceptions (catch (Exception ex)) but they are few and far between and they should be logged if appropriate and documented liberally.
    • Remember always if you do catch an exception and intend to rethrow it, then use throw; not throw ex; lest you lose your call stack and good bits of context.
  • Create a global error handler that logs everything.
    • A user shouldn't ever see an exception dialog or ASP.NET Yellow Screen of Death, but if they do, let them know that you've been notified.
    • {smartassembly} is an easy way to make this happen. So is ELMAH for ASP.NET. (I freakin' love ELMAH)
  • Yes Response.Redirect in ASP.NET causes an internal exception. Yes, it's a bummer, but there's a reason. It was an easy way to stop execution. If you don't like it, call its overload and stop page execution yourself. Personally, I don't sweat that one, but then I avoid Redirects, too.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 31 - Test Driven Development

August 30, '06 Comments [4] Posted in NUnit | Podcast
Sponsored By

My thirty-first Podcast is up. This episode is about Test Driven Development.

We're listed in the iTunes Podcast Directory, so I encourage you to subscribe with a single click (two in Firefox) with the button below. For those of you on slower connections there are lo-fi and torrent-based versions as well.

Subscribe: Feed-icon-16x16 Subscribe to my Podcast in iTunes

This show was FULL of links, so here they are again. They are also always on the show site. Do also remember the archives are always up and they have PDF Transcripts, a little known feature.

Links from the Show

NUnit
NSPEC
TestDriven.NET
NCover
Fowler's Refactoring
MBUnit
NCover Explorer
Intro to TDD
Peli's original article on MBUnit
Guidelines for Test-Driven Development (Psyche!)
TDD Interview with Fowler
CSUnit
Unit Testing in .NET Projects
Resharper
Jay Flower's Doubler
Write Naive Test Code
RoyO - The Art of Unit Testing
Guidelines for Test-Driven Development
Apoorva Muralidhara Essay on TDD
Refactor! from DevExpress
Software Tester Team Center
Refactor Ruthlessly
CodeRush NUnit Templates

NEW COUPON CODE EXCLUSIVELY FOR HANSELMINUTES LISTENERS: The folks at XCeed are giving Hanselminutes listeners that is Coupon Code "hm-20-20." It'll work on their online shop or over the phone. This is an amazing deal, and I encourage you to check our their stuff. The coupon is good for 20% off any component or suite, with or without subscription, for 1 developer all the way up to a site license.

Our sponsors are XCeed, CodeSmith Tools, PeterBlum and the .NET Dev Journal. There's a $100 off CodeSmith coupon for Hanselminutes listeners - it's coupon code HM100. Spread the word, now's the time to buy.

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)

  • The basic MP3 feed is here, and the iPod friendly one is here. There's a number of other ways you can get it (streaming, straight download, etc) that are all up on the site just below the fold. I use iTunes, myself, to listen to most podcasts, but I also use FeedDemon and it's built in support.
  • Note that for now, because of bandwidth constraints, the feeds always have just the current show. If you want to get an old show (and because many Podcasting Clients aren't smart enough to not download the file more than once) you can always find them at http://www.hanselminutes.com.
  • I have, and will, also include the enclosures to this feed you're reading, so if you're already subscribed to ComputerZen and you're not interested in cluttering your life with another feed, you have the choice to get the 'cast as well.
  • If there's a topic you'd like to hear, perhaps one that is better spoken than presented on a blog, or a great tool you can't live without, contact me and I'll get it in the queue!

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

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Making DasBlog work on Mobile Devices

August 29, '06 Comments [12] Posted in ASP.NET | DasBlog
Sponsored By

DasblogblackberryI was screwing around last night with my Blackberry and was frustrated to see how crappy my blog (and most blogs) looked on a small device.

So, here's what I did.

I noticed that you can cast the Request.Browser object in ASP.NET to a System.Web.Mobile.MobileCapabilities. In ASP.NET 1.1, this uses the browsercaps section of your machine.config or web.config. In ASP.NET 2.0, the architecture is much cleaner, using .browser files.

Since DasBlog compiles under ASP.NET 1.1 and typically runs under 1.1, I'll talk about this in the context of ASP.NET 1.1, but the essence is the same.

There's a property called IsMobileDevice on the MobileCapabilities object that most folks consider useless. That's because the default browser caps stuff with ASP.NET 1.1 is poo. Here's a good explanation:

Microsoft pawns the job off on Cyscape.com, which doesn't care about doing the world a service (it's busy selling its competing BrowserHawk product instead).  As a result, machine.config is already woefully out-of-date and unaware of newer browsers like Mozilla/Firefox, Netscape 7, Safari, and Konqueror, so it tells Request.Browser that they are "Netscape 5" (though Safari and Konqueror are wholly unrelated rendering engines).

Cyscape hasn't done the job and instead wants to upsell to their (very capable, but often overkill) application.

Instead I Googled around for Browsercaps XML sections...there are many, and they are in various levels of disarray, but this one from last year was pretty darn good. If you're using ASP/PHP the current Patron Saint of BrowserCaps (non-ASP.NET) is Gary Keith. The ASP.NET one from Chris Maunder at CodeProject is also lovely.

DasBlog supports theming, so I added a bare-bones XHTML-ish mobile-friendly theme for small devices - essentially TinyHTML (my term).

I added this code to the SharedBasePage where we decide what theme to use:

//Are we on a Mobile Device? See if we have a mobile theme and use it instead.

System.Web.Mobile.MobileCapabilities mobile = (System.Web.Mobile.MobileCapabilities)Request.Browser;

if(mobile.IsMobileDevice == true)

{

    theme = themes["mobile"];

    if(theme == null)

    {

        loggingService.AddEvent(new EventDataItem(EventCodes.Error,

            String.Format("If you have a theme called 'mobile' in your themes folder, readers who visit your site via a Mobile Device will automatically get that theme. User-Agent: {0}",Request.UserAgent),

            String.Empty));

    }

    else

    {

        return theme;

    }

}

...continue on...

And boom, shiny, mobile support for this blog. (It is crazy stuff like this at the last minute that keeps 1.9 from being release, but I promise, it's close. For now, remember that unsupported Daily Builds are here: http://blogs.tamtam.nl/paulb/bits/)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.