Last time, we took a dive into what virtualization on Windows Vista is all about, and examined the different run levels available to your application. Like I mentioned before, unless you know for a fact that your app should run with higher privileges, you should always make your application run under asInvoker.
Today, we’re going to look at how to create a UAC-aware Fusion manifest, in order to deliver the best User Experience possible to your customers on Windows Vista.
The manifest file itself is relatively simple: it’s a blob of XML that sits either side-by-side or embedded within your executable. Back in the Windows XP timeframe, there were two ways to give your application Windows XP visual styles. The first was to call the method EnableVisualStyles() on the Application() class in your Main() method. The second was to create a Fusion manifest:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<assemblyIdentity
version="Insert Your Exact Version Number Here"
processorArchitecture="X86"
name="Name of Application"
type="win32"
/>
<description>Description of Application</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
When Windows Vista came along, the simplest way for the UAC team to correctly support various runlevels was by overloading the functionality provided by a Fusion manifest to provide this extra information. You can specify the desired runlevel for your application by adding an extra bit of goop to your application’s manifest. If your app doesn’t have one yet, don’t fret! We’ll handle that, too.
UAC information specified within a Fusion manifest looks like the following:
<!-- Identify the application security requirements. -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
There are two key elements specified within the requestedExecutionLevel:
- level - This is the runlevel we explored last time. Unless you have a very good reason not to, you should always specify asInvoker here.
- uiAccess - Set this to “false” unless you know exactly why you require UI access. Essentially, this parameter specifies whether or not your application requires the ability to drive UI input into other apps. Examples of apps in this class would include assistive technologies like screen readers or automated UI testing frameworks.
The full Fusion manifest updated for Vista will look like this:
<?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="ChimpSoftware.Borealis"
type="win32"
/>
<description>Chimp Software Borealis</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<!-- Identify the application security requirements. -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
Drop this text into a file named MyApplication.exe.manifest, and place it next to your executable. Clearly, MyApplication should be the name of your app. You should also replace the references to Chimp Software Borealis with references to the name of your app (gee, what’s Borealis?). Now, launch your app and then Task Manager. You should see that your application is no longer being virtualized. If you do bad things, like writing to Program Files or the Windows directory, these calls will now promptly fail. This is good, because those are bugs in your app. Go fix ‘em!
Clearly, you still need a way to bundle the manifest with your application. You could simply add the manifest to your setup application, but you’d be better off embedding the manifest directly into your application. Directions for doing this are pretty straightforward for native applications, and instructions already exist on how to do this. Trying to do this for a managed application with VS 2005 is trickier. Next time, I’ll show you how to solve this problem.
Possibly Related Posts:
- Windows System Colors
- Meet UAC - Why you must factor out your apps’ admin components
- Meet UAC - Embedding Manifests in Managed Apps
- Meet UAC - Understanding Virtualization and Run Levels
- An even better screen capture tool
5 Comments
If you’re developing native code using Visual Studio 2005 and not statically linking in the CRT then you need to have a manifest anyway. VC 8 instals the C Run-Time (MSVCRT80.dll, etc.) as a set of side by side assemblies. Visual Studio 2005 automatically generates a manifest for the CRT and embeds it in the binary. You can specify additional manifests through the project properties (Manifest Tool > Input And Output).
I think that http://msdn2.microsoft.com/en-us/library/ms235342(VS.80).aspx sums it up nicely:
“Building Visual C++ projects without manifest generation is not supported. Any C/C++ program built in Visual C++ 2005 has to include a manifest describing
its dependencies on Visual C++ libraries.”
One thing worth keeping in mind when talking about manifests is that from Windows Server 2003 onwards manifests found embedded within binaries take precedence over external manifests, although this is the opposite under XP. Therefore, if you create an external manifest to specify UAC run levels without preventing VC from generating a manifest then the external manifest won’t have any effect.
Thanks for the added detail, Will!
Aaron
The AssemblyIdentity element seems to have no effect. After signing an assembly using signtool.exe with an authenticode certificate, the Application Name shows up as some .tmp file when the UAC prompt appears. Any solution?
No, I don’t have one offhand, unfortunately. You might want to try the official Windows Vista development forums; I’ll bet you can find your answer there.
Good luck!
Aaron
> SugarDaddy
> After signing an assembly using signtool.exe with
> an authenticode certificate, the Application
> Name shows up as some .tmp file when the UAC > prompt appears. Any solution?
Probably there is no VersionInfo in your program. I have fixed same problem now. Solution was adding VersionInfo to my program.