Vista UAC Manifest

Here's a couple of interesting little tidbits for those using Delphi 2007 and trying to create manifest files to require your program to run as Administrator. For those who don't know what this means, we're talking about running a program and receiving the wonderful little pop-up "A program is trying to take over your life"... well, something like that anyway. You will need your program to receive elevated privileges if you want to do certain things. In my particular instance, I wanted to write to the HKEY_CLASSES_ROOT registry entries. This isn't supposed to be a full reference to what a manifest is, how it works, etc., etc. Microsoft has documented the UAC in some depth and I recommend using their documentation if you want to really understand your options.

First, the manifest structure is basically just an XML document that tells Vista how it should handle the program. For elevated privileges, it should look like:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestversion="1.0">
<assemblyidentity version="1.0.0.0" processorarchitecture="X86" name="Vista UAC Compat.Application" type="win32">
<description>WindowsVistaReadiness Application</description>
<trustinfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedprivileges>
<requestedexecutionlevel level="requireAdministrator">
</requestedexecutionlevel>
</requestedprivileges>
</security>
</trustinfo>


(thanks to Henrik Bruhn who helpfully posted the above manifest on borland.public.delphi.non-technical)

Second, D2007 automatically includes a manifest file. If you manually create a manifest file, you wind up with two manifests attached to your program. This will actually create a DCC32 error when you go to compile (duplicate resource). In order to fix this, you have to disable run-time themes under Project/Options/Application. Of course, you then become responsible for inserting the appropriate ComCtrl32 language into the manifest to "upgrade" to the themed ComCtrl32 library that became available in Windows XP. Don't ask me why CodeGear didn't give a little check box to enable this feature. It may have something to do with my fifth point below. At any rate, the updated manifest file (merged with what D2007 automatically includes) looks like:


<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestversion="1.0">
<assemblyidentity type="win32" name="CodeGear RAD Studio" version="11.0.2804.9245" processorarchitecture="*">
<dependency>
<dependentassembly>
<assemblyidentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publickeytoken="6595b64144ccf1df" language="*" processorarchitecture="*">
</assemblyidentity>
</dependentassembly>
<trustinfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedprivileges>
<requestedexecutionlevel level="requireAdministrator" uiaccess="false">
</requestedexecutionlevel>
</requestedprivileges>
</security>
</trustinfo>


Note that the information in the assemblyIdentity can be changed to match your information instead of just blindly copying D2007's information.

Third, you have to include the manifest in your dpr. Make sure you've saved the XML from above as some known file name (vista.manifest in my case). To do this, you will need to create an RC and RES files. D2007 makes this fairly straight-forward. You don't even have to fool with brcc32 anymore. Just create a blank text file and insert


1 24 vista.manifest


in the file. Save that as vistaprog.rc (do not name it the same as either your project or any file in your project, this will cause a resource file conflict.) In your dpr, underneath the


{$R *.res}

add a new line


{$R 'vistaprog.res' 'vistaprog.rc'}

Now, when you do your build, D2007 will automatically compile the RC file, include the vista.manifest and generate a RES file which will be linked into the EXE.

Fourth, you cannot run your program from a substituted (using the subst command) drive. This is probably a minor annoyance for most since subst is used by command line junkies more than anyone else. In my specific case, I have a set of code paths representing versions (i.e., c:\source\v1, c:\source\v2, c:\source\v3) and I use subst to create a working environment that the IDE works with but is totally transparent to which version I'm in. For instance, subst j: c:\source\v? where ? represents the source code version I want to work. This provides a drive letter (j:) that is anchored to that directory. If you do try to run the program from a substed drive, you will see that you get a message "The specified path does not exist. Check the path and try again." If you ran it from the console, you receive the same error message AND a command line message saying "The system cannot find the file xxxx." It works fine if you just move the exe to a normal drive.

There may be a fifth issue, I haven't quite decided on this one yet. I am currently unable to run an elevated program in D2007. I suspect this is because Vista starts the exe, sees the manifest, terminates the exe and restarts it under the new security level. Obviously, this is not going to make the Delphi debugger very happy. I'm still researching this particular aspect of it. If this is truly what is happening, it should make debugging elevated programs a lot of fun.

If you are interested in some other articles on the manifest system, look here, the original thread from Henrick on the newsgroup, here for Steve Trefethen talking about the automatic inclusion of manifest info in D2007, here on the XP manifest, here for a discussion on Windows XP manifest and ComCtrl32, and here for a detailed discussion on UAC. The last link I provided offers a COM factory mechanism for elevating your program as needed instead of the whole executable all the time. For my particular purposes, I just needed global elevation, but the COM factory is a much more elegant solution if you only occasionally need access.

Disclaimer: Since I didn't see a step-by-step guide on how to do this anyway, I threw this together as I figured out what was going on. If you have any questions, ask away and I'll try to help.