With the recent release of the new Microsoft Windows Vista operating system, there is a new certification program that allows us to endorse our applications with a "Certified for Vista" logo as long as it passes a strict testing process. There are 32 tests that the application needs to pass in order to gain the certification. When preparing our application (Fascia – a C# .NET (managed) application) for certification, there were a number of issues and things to consider. It was hard to find the information required to overcome many of the difficulties, so I have put together this article in order to summarise what I have learnt in order that it may assist with future certification attempts.
I have included some code samples that refer to some functionality from the "
DataInterface" namespace. The relevant assemblies in this namespace are discussed towards the end of this article. The source code for these assemblies and a demo program that uses them are available in the download.
Overview of the Tests
Fortunately, the full test scripts and the tools required to perform the tests are freely available. It is therefore possible to run all the tests before submitting the application to give a degree of confidence about whether your application will pass or not. There are a number of helpful resources available on the internet to assist in the preparation process. I have summarised these at the end of this article. The tests are split into three sections:
- Security and Compatibility
Security and Compatibility
User Account Control (UAC) and Elevation
Vista will not let applications perform administrative tasks unless an administrator confirms that it is OK. Even if you are logged on to Vista as the administrator, you still need to confirm administrative tasks as they happen (by entering your password). This process is known as elevation. This is relevant to developers of Vista applications since we need to decide which tasks in our application need administrative privileges. We should try and avoid doing anything that requires administrative privileges and those tasks that do require an administrator need to be separated into distinct executables. All your executables must contain a manifest that indicates the execution level that is required to run them. I explain how to add the manifest to your executables in the text for Test Case 1.
The main executable must have a manifest with a requested execution level of "
asInvoker" (the other options are "
requireAdministrator" and "
highestAvailable"). This means that it can be run without administrator privileges. If the main executable needs administrator privileges straight away and for most of its tasks (this is very unusual), you must apply for a special waiver from Microsoft. If the main program needs to do something that requires administrator privileges, it must shell another executable that has a manifest with a requested execution level of "
requireAdministrator". The button or other control that shells the "
requireAdministrator" program must be denoted with the Vista shield icon. I'll explain how to do that later.
Test Case 1: Verify all of the application's executables contain an embedded manifest that define its execution level
To add a manifest to an executable, create a text file (the manifest) in the following format:
="1.0" ="UTF-8" ="yes"
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="22.214.171.124" processorArchitecture="X86" name="Fascia"
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
Save this file as <executablename>.exe.manifest. Use the tool mt.exe to add the manifest to your compiled executable. It is preferable to have Visual Studio run mt.exe after compilation, using a Post-Build event. The post-build command line should be:
The use of the generic
$(TargetName) etc. mean that this command line may be copied "as is" to any project.
Fascia saves many files to different locations on the disk at runtime. As well as saving files that are created by the user, it also saves log files, debug files, configuration files and exception reports. There are a couple of rules that are enforced by the Vista certification tests and by Vista itself.
- The application must only install files to the application folder (a sub-directory of Program Files) or the user's AppData directories by default. If the install is "per-machine", then there is no correct user AppData folder. In this case, user data must be written during the first run of the program instead of during installation.
- At runtime, files should only be created in the (.NET)
Application.LocalUserAppDataPath (for user specific files) or in the
Application.CommonAppDataPath (for files that apply to all users), modified for Vista as follows:
if(DataInterface.Controls.Vista.Global.RunningVistaOrLater()) publicDir =
For Fascia, this meant going through all the parts of the code that create or modify files and ensure that only these two locations were used. There was an exception to this rule with Fascia. Fascia has automatic update functionality, that results in application files in the "Program Files" directory being updated. This requires administrator privileges, so that part had to be separated into a separate executable marked with a "
Test Case 5: Verify application installed executables and files are signed (Req:1.3)
In order to sign the dlls, we had to obtain an Authenticode certificate from Verisign. This is comprised of a certificate file and a private key file. Use the SignTool.exe program to sign the dlls. We keep our files on a secure server and run a batch file as a post-build event to sign the dlls.
We have two third-party dlls that are not signed. You need to apply for a waiver for such files, by sending the waiver application form to email@example.com. There is a link on the "Innovate on Windows Vista" partner website to the waiver form (see useful resources).
Our application installer was built using Visual Studio 2005. This ensures that it meets the first requirement; that it uses Windows Installer. Visual Studio compiles an installation project to a ".msi" file. A ".msi" file is actually a set of (database) tables that contain data. These raw tables and their contents can be viewed and edited using the "Orca.exe" tool.
Orca has some in-built verification tests that are performed in Test Case 12. These Internal Consistency Evaluators (ICE) ensured that our installation was clean and didn't, for example, attempt to install the same file twice.
Surprisingly, a ".msi" file created with Visual Studio won't pass all the tests for Vista certification. A number of changes need to be made using Orca. Fortunately, Orca can be used to create a transform file that can be applied each time you build the msi file to make the changes that are required. I created two transform files:
- AddMsiRMFileInUse.mst – this creates a dialog required by Test Case 25 that handles files in use during installation. See this post in the MSDN forum for information about this.
- VistaPatch2.mst - this does the following:
See http://www.creativedocs.net/blog/ for information about this.
- In table
AdvtExecuteSequence, drop the only row which has a GUID and a condition set to
- In table
CustomAction, add this row:
MyTargetDir, 51, ARPINSTALLLOCATION, [TARGETDIR]. This ensures that the install location is written to the registry for Test Case 19.
- In table
InstallExecuteSequence, add this row:
MyTargetDir, , 798. This ensures that the install location is written to the registry for Test Case 19.
The transform files can be applied using msitran.exe from the Microsoft Platform SDK for Windows Server 2003 R2. Use the "
-a" option as in the following example:
Msitran.exe -a VistaPatch2.mst Fascia.msi
The final action that has to be taken is to sign the msi file with the Authenticode certificate.
Test Case 30: Verify the application is Restart Manager Aware
If our application needs to be shutdown by Vista as a result of another installation or update, the Vista Restart Manager comes into play. Applications must register for a restart message when they start, using the following code:
When Fascia is restarted, it will be supplied with the command line arguments that were specified in the
Fascia responds to a restart message by saving state and allowing the shutdown to go ahead. To respond to a restart message, override the
WndPrc function of the main window as shown in the following example:
protected override void WndProc(ref Message m)
When Fascia restarts, it detects that it is a restart manager initiated restart by inspecting the command line arguments that were supplied when registering for a restart. The state is restored after the user logs in.
Test Case 31: Verify application does not break into a debugger with the specified AppVerifier checks
The most recent version of the test cases includes a note at the end of Test Case 31 that says that this test case is not applicable to fully managed applications. Since this note was not added until I had finished preparing Fascia for the certification, I spent time ensuring that Fascia would pass this test case anyway. It is reassuring that Fascia is stable enough to pass this test even if it is not a requirement of a managed application.
After fixing several areas of the code that caused a failure of this test, I found that my final failure was fixed by ensuring that the executable was built in release mode. It could be that for managed applications built in release mode; these tests won't fail, although I haven't verified this. I would suggest you build all your managed assemblies in release mode if you too want to see whether your application will pass this test.
There is a known issue if you have any images on your forms that have transparency. This test will fail if you do have such images. I had to replace the images that had transparent sections with ones that didn't have any transparency.
The test specifies that you use the "
AppVerifier" tool to run certain automatic tests on the executable (Exceptions, Handles, Heaps, Locks, Memory and TLS from the Basics checks, DangerousAPIs and DirtyStacks from the Miscellaneous checks). The difficulty comes in debugging any of the errors, since the behaviour is very different when running from Visual Studio. I found that I could only narrow down the specific lines of code that were causing failures by using MessageBox and/or commenting out large areas of code. The failures were ultimately fixed by performing more null checking, especially in areas of code that were surrounded by empty exception handling such as:
Clearly this is bad programming practice anyway, but should certainly be avoided in applications that you want certified.
Test Case 32: Verify that the application only handles exceptions that are known and expected
The notable thing about this test is that if you build an application that has absolutely no try-catch blocks, it will pass. Exceptions must not be caught without being re-thrown, since they need to be thrown so that the Windows Error Reporting can pick them up. Fascia catches exceptions and sends them to a static function that can send a report to a central web service that allows us to diagnose customer problems efficiently. It uses a similar idea to Windows Error Reporting, but was causing the test to fail, since Windows Error Reporting must be used by an application that is a candidate for being certified for Vista. The solution was to call
throw in the
catch block of any exception handler, to ensure that the exceptions were rethrown. Incidentally, if you call
ex is a specific exception that has been caught, the test still fails. You must call
throw with no arguments.
The application must be registered on the winqual site in order to be eligible for Windows Error Reporting.
The source code
.NET Assemblies to Assist in the Certification Process
I wrote two assemblies that wrap some of the functionalities that are required when preparing an application for Vista certification.
DataInterface.Controls.Vista contains controls that are specific to Vista, but also run on Windows XP. It contains two controls; the
CommandLink and the
CommandLink control allows you to create a Vista command link style button. These are the link buttons you see when Vista asks you to confirm elevation. You can see these by clicking on any Vista administrative task such as changing the system time and date. The
ShieldButton control is a normal Windows button that has a
ShowShield boolean property that indicates whether or not to display the Vista shield icon on the button. Useful static code in the assembly is contained in the Global class as follows:
public class Global
internal const int BS_COMMANDLINK = 0x0000000E;
private const uint BCM_SETNOTE = 0x00001609;
private const uint BCM_SETSHIELD = 0x0000160C;
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern IntPtr SendMessage(HandleRef hWnd, UInt32 Msg,
IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr SendMessage(HandleRef hWnd, UInt32 Msg,
IntPtr wParam, string lParam);
public static bool RunningVistaOrLater()
return System.Environment.OSVersion.Version.Major > 5;
To show a shield icon on a button control, the
FlatStyle has to be set to
FlatStyle.System and the
SetShield method needs to be called in the
Global class. Use the
RunningVistaOrLater function to check whether the application is running under Windows Vista before applying any of the Vista styles. The
SetNote method is used to display the note on a
In order to get the shield to show on a
ShieldButton, the following two lines of code must be run when the application first starts:
DataInterface.RestartManager contains code that is used to make an application "RestartManager aware". It wraps the required functionality from the "Kernel32.dll" API. Here is the code:
public class Global
private const Int32 WM_QUERYENDSESSION = 0x0011;
private const Int32 ENDSESSION_CLOSEAPP = 0x1;
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern uint RegisterApplicationRestart
(string pszCommandline, int dwFlags);
public static bool IsRestartMessage(System.Windows.Forms.Message msg)
bool ret = false;
if (msg.Msg == Global.WM_QUERYENDSESSION)
if ((msg.LParam.ToInt32() & Global.ENDSESSION_CLOSEAPP) ==
ret = true;
public static void RegisterApplicationForRestart(string restartCommandLine)
is a demo application that shows how to use the two assemblies described above. It demonstrates four aspects:
RunningVistaOrLater() function is used in the form's constructor in order to determine the text to display on the label at the top of the form.
ShieldButton. This is displayed on the form and has the
ShowShield property set to
true. This will display the shield icon when running in Vista.
CommandLink button. This is displayed on the form and has the
Note property set. This note will be visible when running in Vista.
- The Restart Manager functionality. The application registers with the restart manager in the
Main() function, using specific command line arguments. The
Main() function checks the command line arguments to see if the application was started by the restart manager. The
WndPrc function of the form is overridden in order to detect when the restart manager is closing the program. At this point, we should (quickly) save state.
Points of Interest
The hardest part of preparing Fascia for the certification was discovering all the information required. Hopefully this article has given you a headstart in preparing your application.