views:

205

answers:

3

Starting with Windows Vista, Microsoft added a class of compatibility shims that will allow an application that assumes it has administrative file and registry access to continue to function.

In other words: An application that failed on Windows XP would run on Windows Vista.

These OS provided bug-fixes can be disabled by adding a section to the application manifest, declaring the application should run asInvoker:

<!-- Disable Windows Vista standard user compatability heuristics -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
   <security>
      <requestedPrivileges>
         <requestedExecutionLevel level="asInvoker"/>
      </requestedPrivileges>
   </security>
</trustInfo>

Ideally, a developer would test their application to ensure that it doesn't (needlessly) require administrative privelages. In order for me to test this, i would need to manifest it asInvoker.

But when it comes down to it, i'm not going to release the application to the customer manifested asInvoker. If i did miss something, i don't want the user to be impacted. i want Microsoft's operating system to fix my mistakes. Problem with this solution is:

  • i have to modify the manfiest before release
  • i'll never know about the things i missed, becuase they're just work on Windows Vista.


A similar conundrum comes up with Windows 7's supportedOS manifiest entires. You can add a manifest to the application indicating which version of Windows you were designed and tested for:

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
   <application> 
      <!--The ID below indicates application support for Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
      <!--The ID below indicates application support for Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
   </application> 
</compatibility>

In the case of the supportedOS items, the operating system knows up front which OS you were designed for. This will place your application in the context of Windows Vista if you do not say that you support Windows 7:

alt text

This action is similar to running an application in some Compatibility Mode, e.g.:

  • Windows Server 2008 (Service Pack 1)
  • Windows Vista (Service Pack 2)
  • Windows Vista (Service Pack 1)
  • Windows Vista
  • Windows Server 2003 (Service Pack 1)
  • Windows XP (Service Pack 2)
  • Windows 2000
  • Windows NT 4.0 (Service Pack 5)
  • Windows 98 / Windows Me
  • Windows 95

where you will get a schmorgasboard of compatibilty shims applied, and Windows will emulate old undocumented behaviour in order to help your app from crashing when it depended on that undocumented behaviour.

An example of compatibility shims that Windows 7 will provide for an application running in the Windows Vista context:

  • RPC will use the old private thread pool, rather than the OS thread pool
  • you will be able to Lock the primary video desktop display buffer
  • you will be able to Blit to the primary desktop video buffer without specifying a clipping window
  • you will be vulnerable to a GetOverlappedResult race condition (if you depended on it)
  • you will continue to get Program Compatibilty Assistant (PCA) mitigation

And once again, in order to test my application properly under Windows 7, i have to add the supportsOS manifest entry. But, again, i'm not going to ship the application with that flag, because i don't want to lose the benefit of these shims (e.g. PCA). And, again, if an app has problems that were fixed because it was running in the Vista context: i'll never know about it from our customers - because the app is just working.


Thoughts? Guidance? Best practices?

A: 
littlegreen
i thought about the external manifest. But starting with Windows Server 2003, and newer, any internal manifest is preferred over a .manifest file (http://blogs.msdn.com/junfeng/archive/2009/05/11/internal-manifest-vs-external-manifest.aspx)
Ian Boyd
Well that is even good news, because the solution I describe above is implemented with the internal manifest, *not* the external one. I am afraid I wasn't clear enough.. should I explain it better?
littlegreen
A separate manifest file, in the directory containing the EXE file, **cannot** override the linked-in manifest. i should be able to add a define to not include the manifest, making the software using an external manfiest.
Ian Boyd
Indeed, you are right: another way is to use the #ifdef to choose between the internal and NO manifest, so the external manifest, instead of between two internal manifests. The effect would be the same.
littlegreen
+1  A: 

i'm not going to release the application to the customer manifested asInvoker. If i did miss something, i don't want the user to be impacted.

I think this is a bad approach. My advice is to manifest correctly from the start and test what you deploy.

Microsoft is not going to bend over backwards for everyone's compatibility. They're going to target the most common, high-impact mistakes made by the biggest vendors. If you miss some small issue, the chance of them providing a shim in the future is small.

Every time Microsoft adds a compatibility shim, we all pay a price. There are APIs that don't work the way they should because they had to handle some case in a brain dead way to achieve compatibility with somebody else's bug. This means long, painful debugging sessions, it means wading through longer (or less complete) documentation, and it means little inefficiencies in the OS for everyone. It also means Windows developers are wasting time fixing other people's mistakes instead of improving the OS.

Sometimes these compatibility changes are big hammers that penalize developers who do it right. Many applications don't handle high DPI correctly, so--in the name of compatibility--Vista assumes that no applications handle it correctly (unless they explicitly claim otherwise). Vista applies UI scaling. Applications that didn't handle high-DPI get improved (but suboptimal) results. Applications that did handle high_DPI get degraded results. (And customers who used the good apps see them get worse when they upgrade to Vista and blame Microsoft.) The developers who didn't pay their taxes get help from Microsoft, the rest of us (including Microsoft) get penalized. The only way to avoid this is for everyone to pay their taxes.

In general, Microsoft is getting better at making these compatibility shims more targeted (though Vista was pretty blunt). Nevertheless, there's a little cost to each one.

Follow the best practice during development. Test what you plan to deploy. If it breaks big, Microsoft might fix it for you. Otherwise, you might have to release an update. That's better than everyone suffering a penalty because some developers didn't do the right thing.

Adrian McCarthy
i agree with everything you said. But if the software crashes because of a feature i specifically opted into - then i broke it. i don't think Windows should have shims, i think applications should break, and the company be required to fix them free of charge for all its users. If a company doesn't want to update it, the company lost the source code, or the company doesn't exist, then someone still needs to fix it.
Ian Boyd
A: 

AsInvoker is the correct way to distribute your application!!!

All that says, is run with the user's credentials. It doesn't say 'do something sneaky' or 'use admin rights'.

Without that manifest, you're branding your application as "I'm not aware of UAC, so please provide me whatever hacks you need to make me still maybe function on any system that has UAC"

But if your application doesn't try to do admin-only things - and you can easily test that by simply being logged in as a standard user & then running your app and watching for failures - then AsInvoker is absolutely correct.

This might help you get a handle on it: A Programmer's Exploration of Vista's User Account Control

Mordachai
My application doesn't (intentionally) do anything that is admin-only. This is also true of nearly all applications. And this is why many applications fail when running as a true standard user. And this is why Microsoft created the standard user heuristics on Vista.
Ian Boyd
"and you can easily test that by simply being logged in as a standard user it's not that "easy". There some sometimes difficult to reach code paths that my own testing might never see. If it was easy, then all programs would be bug-free, because every possible scenario was already tested.
Ian Boyd
And finally, take extra special note of the line in my original question, "If i did miss something...". If i did miss something, i want to application to continue to work. After all, it worked in XP - but suddenly it fails in Vista. "Stupid Vista" the customer says. And suddnely the customer refuses to upgrade to Vista because "it broke our important business application."
Ian Boyd
I do hear what you're saying: Ideally, you'd like for MS to use whatever compatibility shims it can come up with to ensure that your application continues to work worry-free on whatever new version of OS they make (or service pack). However, the UAC heuristics make many programs fail in hard to understand and make work-right ways. I have had to support many users of legacy apps which work incorrectly precisely due to MS's compatibility shims, and due to the way that the virtualized registry and file system work. Marking your application as being pre-Vista doesn't isolate your from problems
Mordachai
Mordachai
This same issue happens for folders in the filesystem. And there are even more subtle problems that arise due to MSs shims. Bottom line: their shims are worse than helpful. In most cases, your application expected to do what it asked for. If something terribly clever is done underneath - its anyone's guess as to whether it was truly clever enough to work right. In my experience so far: almost never. MS's batting avg. sucks hard.
Mordachai