Manifesting for Compatibility on Windows 7


Normally, I’m talking about how to fix applications here, but I want to digress and instead talk about how to help us fix things up in future versions of Windows for you.

The most frequently used application fix is a version lie. We have to lie to applications that are doing the wrong thing (explicit checks for equality), as well as applications that tried to do the right thing but implemented it wrong.

There is a new feature in Windows 7 which lets you tell us which version of Windows you are designed for. Of course, that doesn’t help you out if you’re testing for a minimum version, but if you’re testing for a maximum version (by using equality or <) then this is a better mechanism to communicate that. But, of course, it requires communication – you have to tell us what you have designed for in order for us to react to that. And you have to trust us that we’ll do the right thing. (I’d understand if you don’t.) But our hope is that you can put more of the burden on us to keep your application working, rather than taking matters into your own hand (which, in the end, is actually much harder for us since we have to figure out what everyone did independently to arrive at their solutions).

The application manifest now includes a new section, called Compatibility, for you to communicate which version of Windows you were designed for. It looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!–Windows 7–>
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!–Windows Vista–>
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
    </application>
  </compatibility>
</assembly>

This setting runs fairly deep. In fact, you can see that we set the operating system context. If you launch the Resource Monitor tool in Windows 7 (which just reeks of Mark Russinovich, so I know he had some hand in it), you can add a column to display the Operating System Context:

image

What we have put in place is a mechanism by which we can make specific changes to the OS, target the fixed ones at those in the current operating system context, and target the old behavior at applications designed for previous versions. We can use this metadata, if we have it, for all kinds of application compatibility solutions – from switchpoints (introduced in Windows 7) to future implementations of lightweight virtualization.

But this all hinges on people adding the manifest section to their applications. (Which, of course, means we need to work with tool vendors, including our own.)

But one question which I had:

What the f* is with the GUIDs?

We’ve just never made versioning easy. GetVersion was hard to use. GetVersionEx was easier to use, and easier to use wrong. VerifyVersionInfo was a good idea, but too hard to use.

And here we go again.

The argument for GUIDs: Nobody knows what the GUID for Windows 8 is going to be yet. Not even us. So, by using GUIDs, we prevent somebody from claiming compatibility with an operating system they can’t possibly have tested with. (Odd that we’d be so against such a thing in one group, while the IE team gives you the X-UA-Compatible option of edge to do exactly that.)

The argument against GUIDs: You’re punishing the good guys in order to prevent the bad guys from shooting themselves in the foot. If I test something on Windows 8, and add its GUID to my manifest, I’m going to get both the Windows 8 and Windows 7 fixes (since the OS will simply look at the highest version and apply all previous fixes). But, if I *only* put in the Windows 8 GUID, on Windows 7, I won’t recognize the Windows 8 GUID (since it doesn’t exist yet), and not only will I not give it the Windows 8 fixes, I won’t give it the Windows 7 fixes either. And, if the only fixes I actually needed were the Windows 7 ones, I just broke the app.

Oy. Can you tell which side of the fence I sit on? Then again, the counter to that is, if I had tested it on Windows 7, I could easily add that GUID as well, and all becomes right again. It just means that people have to understand that including any and all GUIDs from tested operating systems is important.

So, here I am writing that.

In addition to specifying the target version, you should specify every version that you’ve tested on. Right now, it doesn’t make a whole lot of difference (since Windows Vista isn’t even looking for this section of the manifest) but the more you can tell us, the more work we can do to help keep your application working in the future. And anything that can help us keep your application working into the future definitely makes everyone more happy. I’ve got my fingers crossed that this gets some uptake…

Comments (27)

  1. Wow! Great idea for Windows. But I wonder will the burden make Windows itself too tired. Hope not 😀

  2. ABC says:

    Hi Chris,

    So we can directly idenfify on which OS this process is compatible. This is really very good. This will reduce our efforts in identifying the compatible issues.

  3. Imtiaz says:

    Our setup.exe is intermittently running in Vista Compatibility mode on its own, we do not want it to run in Vista mode on Windows 7. Adding the compatibility section with ‘Windows 7 GUID’ in the ‘embedded manifest file’ for setup.exe is not helping. We are using Windows 7 Beta 2. The GetversionEX is returning 6.0 in Vista mode as expected.

    Do you know how I can make use of compatibility section in manifest to force the app to not run in Vista Compatibility mode?

  4. Imtiaz,

    Is there an MSI involved, or is it pure setup.exe?

  5. Imtiaz says:

    Thanks for the reply, I really appreciate your help.

    The setup.exe is a C++ executable which copies MSIs to a temp location (it also install prerequiste such as .NET ‘dotnetfx.exe’ etc ) and then makes a call to  a C#  executable.

    When I look at the OS in Resouce monitor , using ‘Win 7 release Candidate 1’, it is showing that the C# exe is being started in Vista compatibility mode.

  6. You need to manifest the exe per the above post in order to set switchback to Windows 7 mode. It’s not full Windows Vista compatibility mode – just getting different switchpoints. Is it causing your application to have a problem?

  7. Imtiaz says:

    Thanks, my manifest has the lines recommended above, I am pasting it here, do you see any issue, it is not working:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

      <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Setup" type="win32"/>

         <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">

         <security>

            <requestedPrivileges>

               <requestedExecutionLevel level="requireAdministrator"/>

               </requestedPrivileges>

         </security>

      </trustInfo>

    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">

    <application>

     <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>

     </application>

    </compatibility>

    </assembly>

  8. Imtiaz says:

    Yes, it is causing a problem. We would like to detect a native Windows 7 OS and abort installation.

  9. The compatibility manifest has nothing to do with version checks. Try using the VersionNT property in your MSI: http://msdn.microsoft.com/en-us/library/aa372495.aspx.

    Why are you aborting installation, though? That’s exactly why we have version lies all over the place – because so much software just says "no thanks" even though it works just fine, which makes customers sad and appcompat busy undoing what you’ve done.

  10. JaneFleming says:

    I’ve been having a discussion with another developer about the merits of including GUIDs for both Win7 and Vista in the manifest section.

    He’s of the opinion that:

    "The Windows 7 GUID should be used if the application provides Windows 7 compatibility.

    The Windows Vista GUID should be used if the application should use Vista-specific functionality on Windows 7."

    Can you point me at a definitive resource/answer?

    TIA

  11. Imtiaz says:

    Thanks for reply.

    The MSI we are executing within our executable is a Microsoft MSI, I can not modify it to set NTVersion property.

    We want to abort the installation because user are installing our current version  (not tested on Win 7) on Windows 7 , in some cases on Beta and then expecting us to provide them an upgrade to later OS, support for issues related to Windows 7 environment.

    We would also Like to detect the Windows 7 OS version in our next release to make decision as to what sub components to install.

    Thanks

  12. Jane – Right now, the only difference when you manifest is the switchpoints that are raised – these are detailed in the Application Quality Cookbook (and are still somewhat in flux). If you’re writing code on Windows 7, then I’d use the Windows 7 manifest and get the new behavior. It also clues us in the future that you are aware of the Windows 7 environment.

    Imtiaz – I don’t know what to tell you. I know from an app compat perspective, getting around version checks is easy, but so frequent as to be annoying. Support is a business matter. I get what you’re trying to do. But refusing to install is rude and causes customers to work around your efforts to do that. Notifying lack of support is different. I’m not sure why you’d be mucking around with one of our MSIs though? Very confused.

  13. JaneFleming says:

    Thanks, Chris, but I’m OLD and blonde and I need things spelled out <g>.

    By "I’d use the Windows 7 manifest" do you mean:

    – use the example you show at the top of this blog (GUIDs for both Vista and Win7)

    – or –

    – include only the Win7 GUID

    I’ve been using Vista-aware manifests and code-signing my stuff for more than 2 1/2 years.  But in adding the compatibility section to the manifests I’ve been using, I’d like to know the rationale behind the choice of including both GUIDs or only one.

    I’ve been enjoying your posts, BTW.  Thank you.

  14. Hi Jane,

    Adding the Windows Vista GUID won’t result in any variation in behavior for your application on Windows 7. What it will do is communicate to somebody that you support both Windows Vista and Windows 7. From an OS perspective, just having the Windows 7 manifest means that we’ll treat you as Windows 7 aware, and give you the Windows 7 switchpoints. Adding the Windows Vista GUID results in no change in behavior right now, and would simply be to communicate to people later on. Does that make sense?

    It’s confusing, I know. I told them that.

    Thanks,

    Chris

  15. JaneFleming says:

    Yes!

    Thank you for the direct response 🙂

    Now to further reveal my ignorance…  could you point me at a link that explains your use of the term "switchpoint"?  

    Jane

  16. Hi Jane,

    Switchpoints are the "divergent behavior" described in the cookbook:

    http://msdn.microsoft.com/en-us/library/dd371711(VS.85).aspx

    Chris

  17. JaneFleming says:

    Thanks.

    That’s what I thought, but I hadn’t run across the term "switchpoint" and have learned over the years not to assume 😉

    Jane

  18. JeremyDrake says:

    So are the new tags "compatibility" "application" and "supportedOS" case sensitive?  The word document at http://code.msdn.microsoft.com/Windows7AppQuality show the tags with upper case first letters (and this is how I did my manifests).  However, using the resource monitor tool (thanks for mentioning that, BTW) shows my processes still say Windows Vista rather than Windows 7.  If I make the tags lower case instead, I get an error "The application has failed to start because its side-by-side configuration is incorrect."  This is on the 32-bit edition, the 64-bit edition running wow64 doesn’t give the error.

    My manifest also has the section for comctl32 6 and the requiredPrivileges section.

    Thanks,

    Jeremy

  19. JeremyDrake says:

    I think I figured it out.  The tag names are case sensitive, and so are the attribute names.  My problem when using the lower case compatibility, supportedOS, and application tags was that I was using ID instead of Id (uppercase I lowercase d).  Once I made that change, the sxs error went away and the resource monitor showed me as Windows 7.

    Somebody should really update those docs on http://code.msdn.microsoft.com/Windows7AppQuality, and probably make a big bold NOTE about the case sensitivity, and the funny capitalization of Id (espeically considering every other attribute name in my manifest has a lower case first letter).

  20. Hi Jeremy,

    Sorry for the delay. I’m at TechEd and running behind on, well, everything. But I forwarded this feedback along to make sure that everything is correct in all the right places. Thanks for forwarding this along – we’ll make sure we get it sorted out.

  21. Kirill says:

    I have tested several tags in Windows 7 RC based on ‘Operation System Context’ column of Resource Monitor.

    Should be in mind that Resource Monitor may display incorrect information about the context of the process.

    Here are the results:

    1. "<SupportedOS ID…" = running in Windows Vista context

    2. "<SupportedOS Id…" = running in Windows Vista context

    3. "<SupportedOS id…" = running in Windows Vista context

    4. "<supportedOS ID…" = error "The application has failed to start…"

    5. "<supportedOS Id…" = WOW! running in Windows 7 context

    6. "<supportedOS id…" = error "The application has failed to start…"

    7. "<supportedos ID…" = running in Windows Vista context

    8. "<supportedos Id…" = running in Windows Vista context

    9. "<supportedos id…" = running in Windows Vista context

    10. "<SUPPORTEDOS ID…" = running in Windows Vista context

    11. "<SUPPORTEDOS Id…" = running in Windows Vista context

    12. "<SUPPORTEDOS id…" = running in Windows Vista context

    So the proper tag is 5 at least in Release Candidate.

  22. Hi Kirill,

    Yes, it turns out that the folks who wrote the entry for the Application Quality Cookbook were unaware that the manifest was case sensitive. Thanks to Jeremy, they are aware now, and have updated the cookbook. Now we’re just waiting for it to go live…

    Thanks for the feedback and for poking around!

  23. JeremyDrake says:

    As long as they’re fixing things… There are also some issues with the XML comments in that document.  For example:

    <!—The ID below indicates application support for Windows Vista/>

    First of all, that’s an em-dash following <!, where there should be a –.  And secondly, I’m pretty sure /> won’t work to close a comment in XML, it should be –>.

  24. Mattias says:

    Hi Chris,

    I find your blog really useful. Thank you!

    If I understand this post correctly (I really start to doubt it as I just cannot get it to work), programs are run in Vista Operating System Context, unless the win7 compatibility tag is included in the manifest.

    My conclusion is that to make sure that an app truly is Win7 compatible, you must insert the Win7 compatibility GUID into its mainfest (although most likely running it in Vista OS context would work perfectly well).

    My problem is that no matter what I put in the manifest, I just can’t get my program to run in Windows 7 compatibility mode.

    I have been trying out different combinations of case, but I assume the manifest posted in this post is correct and could be applied to any exe, resulting in the program running in Windows 7 compatibility mode.

    My best shot (that still fails):

    I copied the xml code from above into a text file. Saved it.

    I used the Resource Hacker tool to enter the manifest into the exe according to the instructions in:

    http://www.blitzbasic.co.nz/Community/posts.php?topic=65756

    I extracted the manifest info and this is what it contains:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

     <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">

       <application>

         <!–Windows 7–>

         <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />

         <!–Windows Vista–>

         <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />

       </application>

     </compatibility>

    </assembly>

    As far as I can see, exactly the same text as above. Have I misinterpreted the concept or misspelled the manifest?

    I also tried entering the text into an external manifest (filename.exe.manifest) but without success.

    I’m using a german Win7RC1 (build 7100)

    Thankful for any response on this, as I have no idea about how to proceed.

  25. Mattias – I’d try using the mt.exe tool rather than hacking up the resources manually. Are you sure there isn’t already a manifest in there? If there is, then you can just extract it with mt.exe, edit it, and then inject the modified one with mt.exe. This tool is part of the Windows SDK.

  26. Imtiaz says:

    Chris,

    Do you have any recommendation on how to detect the correct OS (Windows 7 to be specific) outside MSI.

    Our setup.exe is a C++ program. We can not use VersionNT (which is a Windows installer property).

    Thanks

    Imtiaz

  27. Imtiaz,

    A setup.exe wouldn’t be affected by the fact that we’re shimming msiexec.exe, so you should be able to just call GetVersion(Ex).