External manifests can be very frustrating – they never seem to behave as documented. After a long session of forehead-repeatedly-meets-wall one of the greatest sources of frustration has been unearthed.
For administrators (IT Pros), an EXE from a commercial software vendor may be manifested (or re-manifested) to accomplish one of the following objectives:
- disable UAC Virtualization (by manifesting “asInvoker”)
- change the requested execution level (to force or suppress and admin prompt)
- to prevent Program Compatibility Assistant (PCA) from activating (using compatibility or switchback manifesting)
In the course Win7 LUA/Non-Admin Application Integration Engineer (ENG-60), we have a lab where students configure an external manifest. Frustratingly this lab would result in a portion of students having their manifest ignored.
As students experimented there was no consistent pattern to how or whether they were able to resolve the manifest being ignored. For some it worked fine first time through, for others the manifest would only be recognized after logging off and on, for some it required a reboot and for others not even a reboot fixed it. The eventlog for the source “SidebySide” showed nothing and running sxstrace.exe came up empty.
So I re-wrote the entire lab with a completely different EXE! When I did the final run through, my manifest was IGNORED! You’ve heard of road rage? I had code rage.
Code-rage fueled Googling finally yielded some obscure hints and I was able to piece together an external manifest lab that worked reliably.
The Microsoft documentation on external manifests would lead one to conclude that as long as an EXE does not have an embedded manifest, an external manifest will be read and used instead.
The truth, however, is that manifests are cached in the Activation Context Cache. The activation context cache is a mysterious entity that does not seem to be discussed directly in MSDN documentation. There is a smattering of MSDN blog posts and blog comments that must be divined like tea leaves for a hazy picture of what is going on. (If you know of an official MSDN document, please let me know with our contact us form!)
This cache is resident in memory and there is no way to give a command to flush it. Allegedly a reboot should flush it. However, this does not always do the trick as evidenced by my own experience and the comments of others.
The secret sauce here is that if you change the EXE’s modification date time stamp, the loader will look again for a manifest. This seems to work reliably every time.
I don’t usually publish a complete detailed test sequence, but this is such an insidious problem I thought it would be great if you had the information to prove this out yourself so that you can start trusting that you know how to handle the problem:
- Download and install Digital Photo Fixer from Icegiant software at http://www.icegiant.com/.
This is just a simple program that I know does not have an internal manifest.
- Launch digitalPhotoFixer.exe
- From an ELEVATED text editor, create a .manifest (digitalPhotoFixer.exe.manifest) file that manifests the EXE to requireAdministrator. (You can simply copy one from our manifest templates) BE CAREFUL to elevate when editing .manifest files because they can also be UAC Virtualized. A registry key that prevents UAC virtualization of .manifests is included in the utilities here.
- Launch digitalPhotoFixer.exe again.
- OBSERVE: No elevation prompt.
- If you run sxstrace.exe (a handy script to do that is here) – there will be no records.
- Check the eventlog for SideBySide events – nada.
- Now change the modification date of the EXE. The powershell script touch.ps1 attached to this article is designed to do this job for you or you can use this powershell oneliner: “powershell Set-ItemProperty digitalPhotoFixer.exe LastWriteTime (Get-Date)”
- Launch digitalPhotoFixer.exe again and voila!
Now let's see how deep the rabbit hole goes...
- Change the manifest to asInvoker.
- Change the modification date on digitalPhotoFixer.exe
- Launch digitalPhotoFixer.exe (to cache the manifest details)
- Optional: check it’s virtualization status – should be “Disabled” if the manifest is being used.
- Change the manifest to “requireAdministrator”
- Launch digitalPhotoFixer.exe (WITHOUT changing the exe modification date)
- You should get this strange error (I get it everytime):
Figure 1 – The requested operation requires elevation.
This is a head scratcher if you don’t know what is going on because it’s obvious the operation requires elevation when the EXE was just manifested to prompt for elevation. The message is actually generated by the main instance of explorer.exe. I have to guess that the Activation Context Caching is has somehow cached not only: a) the fact that a manifest exists, but b) the actual requestedExecutionLevel – but later, the loader reads the manifest.
This is a confusing result – especially since sxstrace.exe shows nothing in this circumstance and there are no SideBySide event log messages.
When a “requireAdministrator” manifest is cached and I edit the manifest to “asInvoker” I do seem to consistently get the proper manifesting of asInvoker – which is an extremely good thing since leaving it cached to requireAdministrator is obviously a problem.
What I do know is that if I update the modification date stamp of the EXE whenever the manifest the manifest is updated, the results are predictable – it works as expected.
When an application is being distributed, it is, of course distributed with a final manifest that is not constantly edited – so it will generally work as expected. However, when you are editing the manifest to test various configurations or need to update one that is already distributed – this can drive you crazy.
- If you the need to have a manifest rescanned, change the modification date of the manifested .EXE. “Touch” changes the modified stamp to the current date and time, but it can be any time as long as it is different. It also does not need to be newer than the modification date of the .manifest.
- If you need to have all manifests rescanned, change the registry key HKLM \SOFTWARE\ Microsoft\Windows\ CurrentVersion\ SideBySide\PublisherPolicyChangeTime. CAUTION: I do not know what else this affects, but it seems to be a relatively arbitrary value. You probably want to keep it the same length. Maybe increment it. Could even put a runonce key entry in to decrement it back to it’s previous value.
Others things I tested that help define how the Activation Context Cache works (maybe some of this will spark some further testing and investigation by some of you):
- TEST RESULT: Back dating the file modified time for the .manifest to be before the .EXE modified date FAILED to cause manifest to be rescanned.
- TEST RESULT: Updated version in manifest FAILED to cause manifest to be rescanned.
- TEST RESULT: Updated description in manifest FAILED to cause manifest to be rescanned.
- OBSERVATION: Editing a manifest from requireAdministrator to asInvoker seems to be picked up without using any method to invalidate the cache entry.
- INFORMATION: No regression testing was done using the requestedExecutionLevel=highestAvailable.
- OBSERVATION: The non-exported function BaseSrvSxsGetCacheKey in sxssrv.dll appears to be the one that checks the value of the registration key HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide\PublisherPolicyChangeTime, lending to support to the idea it somehow provides cache aging information for the Activation Context Cache.
- TEST RESULT: Changing modification of .EXE back one second did cause the manifest to be rescaned, so the comparison process is doing “not equal” instead of “greater than” to some other value.
- OBSERVATION: It does not appear to matter if which file has a newer modification date (.EXE or .manifest)
- TEST RESULT: Changing the Created date of the .EXE does not cause a rescan of the manifest.
- TEST RESULT: Changed value of PublisherPolicyChangeTime to 10. System worked as normal across multiple tests, showing that this value may be arbitrary.
- TEST RESULT: Changing PublisherPolicyChangeTime seems to rescan all manifests. (tested with two individual apps)
- TEST RESULT: Changing PublisherPolicyChangeTime does not cause manifest rescans to be done all the time until the next reboot (falsified hypothesis that PublisherPolicyChangeTime might read by csrss.exe at bootup and not re-read until restart).
- TEST RESULT: Reboot does not change PublisherPolicyChangeTime, even if it has been altered to a custom value.
- OBSERVATION: The folder C:\Windows\winsxs\ManifestCache and .bin file in it have a date a couple weeks back – does not seem to be related to the problem of ignored manifests.
- OBSERVATION: Researched exported functions on sxs.dll, sxssrv.dll, sxsstore.dll to see if calling any of these using RunDll32.exe would flush the cache. Only found one that could be called like this: “rundll32 sxs.dll,SxspRunDllDeleteDirectory C:\WINDOWS\WinSxS\InstallTemp\836017”
Check out our full set of manifest utilities.