March, 2009

Larry Osterman's WebLog

Confessions of an Old Fogey
  • Larry Osterman's WebLog

    Well Hello Daniel!

    • 3 Comments

    Gaarggghh.  I can't believe I didn't write about this.

     

    Tonight is the first night of previews for Daniel's first show on a professional stage.  He's appearing as a performance intern at the 5th Avenue Theatre's production of "Hello Dolly!" starring Jenifer Lewis and Pat Cashman.

     

    Daniel has been working his butt off for the past 3 weeks rehearsing every day for the show (12 hours a day for the past week) and tonight the curtain rises for the first time on the production.

    As a performance intern, he is a member of the ensemble.  Most of the time he sits backstage in a booth with the other interns providing vocal support for the cast but he IS on stage for one big number (As the Parade Passes By).

     

    Valorie and I aren't seeing the show until Thursday evening (the official opening night) but I can't wait to see it.  I've been hearing so many great things about this production (especially the Waiters Gallop scene in the Harmonia Gardens - Daniel says it's completely insane) so I'm really looking forward to it.

     

    Ok, enough gushing.  Come see the show, it should be great!

  • Larry Osterman's WebLog

    Delay Load is not a good way to check for functionality

    • 15 Comments

    On my previous post, Koro made the following comment:

    “Don't ever check windows versions.  Instead check for functionality being present or not."

    You can't always do that.

    Do I want to add a __try/__except to catch delay-load exceptions around every UxTheme call or just do:

    g_bTheme=(g_bWinNT&&(g_nWinVer>0x00050001));

    Then check that flag before calling OpenThemeData?

    In some other cases too (all the Crypt Hash functions - trying to compute an MD5) the functions is documented as working fine in Win98 but it just fails - there is no way to know except of checking the version beforewards.

    At least, as implied earlier, I just pack the Windows version in a DWORD at program startup to avoid nasty version comparision errors.

    IMHO Koro’s misusing the delayload functionality.

     

    DelayLoad is primarily a performance tool – when you DelayLoad a function, a tiny stub for the DelayLoad function is inserted into your application which calls LoadLibrary/GetProcAddress on the function.  That then means that when your application is launched, the loader doesn’t resolve references to the DelayLoaded function and thus your application will launch faster.

    For example many components in the OS delay load WINMM.DLL because all they use in WINMM is the PlaySound API, and even then they only use it on relatively rare circumstances.  By delayloading WINMM.DLL they avoid having the performance penalty of having WINMM.DLL loaded into their address until it’s needed.

     

    As Koro mentioned, DelayLoad can also be used as a mechanism to check to see if a particular piece of OS functionality is present, but the challenge is that now you need to wrap every API call with an exception handler (or you need to specify a delay load handler that provides a more reasonable default behavior).  Personally I wouldn’t do that – instead I’d manually call LoadLibrary/GetProcAddress to load the required functions because it allows you to have complete control over when you access over your error handling.  It also allows you to avoid using structured exception handling (which should be avoided if at all possible).

     

    If you DO have need to use DelayLoad as a functionality check, you could try this trick (which works only for Koro’s problem).  Instead of wrapping all the theme API calls with SEH, you just add code to your app like this (I haven’t compiled this code, it’s just an example):

    BOOL g_EnableThemes = FALSE;
    __try
    {
        g_EnableThemes = IsThemeActive();
    }
    __except(<Your Exception Filter>)
    {
    }
    if (g_EnableThemes)

    {
    g_ThemeHandle = OpenThemeData(…)





    }

    In other words check for functionality being enabled once with an exception handler and later on use just the EnableThemes global variable to key off the behavior.

    But this doesn’t change the fact that (IMHO) you’re abusing the DelayLoad functionality and using it as a versioning mechanism.

  • Larry Osterman's WebLog

    Checking file versions is surprisingly hard.

    • 28 Comments

    I was wandering around the web the other day and ran into this post.  In general I don’t have many issues with the post, until you get to the bottom of the article.  The author mentions that his code only runs on Win7 or newer so he helpfully included a check to make sure that his code only runs on WIn7:

    // Example in C#.
    
    internal bool SupportsTaskProgress() {
        if (System.Environment.OSVersion.Version.Major >= 6) {
            if (System.Environment.OSVersion.Version.Minor >= 1) {
                return true;
            }
        }
        return false;
    }

    This is a great example of why it’s so hard to write code that checks for versions.  The problem here is that this code is highly likely to fail to work on the next version of Windows (or whenever Windows 7.0 is released).  In that case SupportsTaskProgress will incorrectly return false.

     

    Personally I wouldn’t even bother writing the SupportsTaskProgress function this way.  Instead I’d check for the “new TaskbarLib.TaskbarList()” call to return NULL and assume that if it returned NULL the API call wasn’t supported (the non COM interop equivalent would be to check for a failure on the call to CoCreateInstance).  That way the code would work even if (for some obscure reason) the taskbar logic was ported to a previous OS version.

     

    If I simply HAD to keep the SupportsTaskProgress function, I’d rewrite it as:

    // Example in C#.
    
    internal bool SupportsTaskProgress() {
        if (System.Environment.OSVersion.Version.Major >= 6) {
            if (System.Environment.OSVersion.Version.Major == 6) {
    if (System.Environment.OSVersion.Version.Minor >= 1) { return true;
    }
    return false; }
    return true; } return false; }

    That way it would only check for minor version being greater than 1 if the major version is 6.  I suspect that this code could be tightened up further as well.

     

    This is a part of the reason that picking a version number for the OS is so complicated.

Page 1 of 1 (3 items)