One of the classes of shims that people find the easiest to understand are the version lie shims. In essence, we have shims that can compensate for the fact that so many developers' keyboards were shipped with a defective > key (and the failure rate of this key on developer keyboards is astonishing). They work by just returning a different value from the GetVersion(Ex) APIs, depending on which operating system you selected. It all makes sense, so people start trying to play around with it. Time and time again, I have had people try to cook up a quick C# or VB.NET application that checks the version, tried to version lie to it, and had the version lie not appear to do anything.

What's going on?

Well, if you want to dig in, you can fire up Compatibility Administrator with the (super secret) /x command line switch. This shows you more details than you would ever want to know. The CompatAdmin team did a really good job of not hiding anything you actually need to know, so the only reason you'd ever rationally want to use this switch is to check something specific such as this, and not because you'd need to in order to get work done.

OK, so now that you have CompatAdmin started, under the System Database, expand the Compatibility Fixes list. With the /x switch, you'll notice that the WinXPSP2VersionLie now has a plus sign - if you expand this, you'll see a list of modules that have a red diamond next to them. These are modules that this shim specifically excludes. Among these? The .NET Framework modules.

You see, the .NET Framework doesn't take too kindly to being lied to. They do version checks to determine how to implement certain things, and thinking they're running down-level isn't so great. So, we intentionally exclude these modules, and, consequently, we intentionally exclude the code that you're writing that these modules are JITting and executing. Not that we wanted to do so, but the infrastructure didn't give us a great way to separate these out. We either lied to everything, or we lied to nothing. It was worse to lie to everything, so we didn't.

Several people notice this because we happened to post a demo application on http://devreadiness.org (which is being phased out now) that was managed, but used a version lie. The exclusion of .NET apps was added pretty late in the cycle for this shim, after this app was written and released, and nobody went back and updated it.

So, what do you do if you want to demo? Well, if you poke around a bit longer, you'll notice that it's only the XP shims that exclude the .NET Framework. So, technically you could version lie for Windows 2000 against a managed app and it would work. However, the same logic applies. We don't explicitly block it, but the fact that we block it is because it's a bad idea not to, and it remains a bad idea not to even when we don't block it. But for a demo, you could get the version lie done.

The other thing to do is to just write native code for your demo, which is how I demo. Here's some code that will do a version check:

void VersionTest() {
    OSVERSIONINFO osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx(&osvi);
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
        TaskDialog(NULL, NULL, TEXT("Version Test"), TEXT("Tested for Windows XP and succeeded"), TEXT("This test runs a version check for version 5.1"), TDCBF_CLOSE_BUTTON, TD_INFORMATION_ICON, NULL);
    } else {
        TaskDialog(NULL, NULL, TEXT("Version Test"), TEXT("Tested for Windows XP and failed"), TEXT("This test runs a version check for version 5.1"), TDCBF_CLOSE_BUTTON, TD_ERROR_ICON, NULL);
    }
}

For real-life applications that need a version lie, well, if the application is managed, you'll have to change the code. This is something you can't, and shouldn't, shim up.

So, if you notice the version lie isn't working, and the application is managed, then my spidey sense tells me you're trying to shim it up with an XP version lie - and that's not going to work.