Date: | May 31, 2007 / year-entry #194 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20070531-00/?p=26623 |
Comments: | 23 |
Summary: | New in Visual C++ 2005 is the ability to specify a manifest dependency via a #pragma directive. This greatly simplifies using version 6 of the shell common controls. You just have to drop the line // do not use - see discussion below #pragma comment(linker, \ "\"/manifestdependency:type='Win32′ "\ "name='Microsoft.Windows.Common-Controls' "\ "version='6.0.0.0′ "\ "processorArchitecture='X86′ "\ "publicKeyToken='6595b64144ccf1df' "\... |
New in Visual C++ 2005 is the ability to
specify a manifest
dependency via a // do not use - see discussion below #pragma comment(linker, \ "\"/manifestdependency:type='Win32' "\ "name='Microsoft.Windows.Common-Controls' "\ "version='6.0.0.0' "\ "processorArchitecture='X86' "\ "publicKeyToken='6595b64144ccf1df' "\ "language='*'\"") into your program and the linker will do the rest. Note that the processor architecture is hard-coded into the above directive, which means that if you are targetting x64, you'll get the wrong manifest. To fix that, we need to do some preprocessor munging. #if defined(_M_IX86) #define MANIFEST_PROCESSORARCHITECTURE "x86" #elif defined(_M_AMD64) #define MANIFEST_PROCESSORARCHITECTURE "amd64" #elif defined(_M_IA64) #define MANIFEST_PROCESSORARCHITECTURE "ia64" #else #error Unknown processor architecture. #endif #pragma comment(linker, \ "\"/manifestdependency:type='Win32' "\ "name='Microsoft.Windows.Common-Controls' "\ "version='6.0.0.0' "\ "processorArchitecture='" MANIFEST_PROCESSORARCHITECTURE "' "\ "publicKeyToken='6595b64144ccf1df' "\ "language='*'\"") Update: I didn't know that * is allowed here to indicate "all architectures". That simplifies matters greatly. #pragma comment(linker, \ "\"/manifestdependency:type='Win32' "\ "name='Microsoft.Windows.Common-Controls' "\ "version='6.0.0.0' "\ "processorArchitecture='*' "\ "publicKeyToken='6595b64144ccf1df' "\ "language='*'\"") Nitpicker's corner * That wasn't a footnote marker. |
Comments (23)
Comments are closed. |
A very useful tip. Thanks!
What would be nice is if the common controls headers included this. (Maybe hidden under a #ifdef USE_AUTOMANIFEST or something for compatibility).
@stu well, actually, if you use WTL (Windows template library http://wtl.sourceforge.net/), it gets automagically included.
Anyway, the point is, is there any better way of doing this? Like how you can add references in the .net framework? Those magical values (publicKeyToken) baffles me (how in the world did you get that value) as if they’re illegal serial keys floating around the net.
This is indeed very useful. Now, we just need a way to specify a requestedExecutionLevel for Vista via a pragma directive.
what’s wrong with specifying a ‘*’ for processorArchitecture?
Normally every time I read the Nitpicker’s corner I feel sorry for you that you have to put it in, but today it made me laugh! Thanks! Glad to know you can still have a sense of humor amidst all of the criticism you get, although some days that must be harder than others!
How do you tell Visual C++ 2005 not to create any manifest-files at all?
BOFH: You read the documentation.
The Linker Options page in MSDN lists all the options the linker understands. One of these is /MANIFEST. Reading the page for that tells you that /MANIFEST:NO tells it not to generate a manifest.
The same page tells you how to turn the feature off in the development environment, both by navigating the project properties dialog and through a macro.
Manifests aren’t just a click away already? Surely that’s sort of important. Then again, I am used to Java IDEs where manifests are critically important: maybe they’re optional in C++?
The answer to the asterisk problem is simple – change from asterisks to daggers.
Obviously, since you can’t use a dagger as a footnote marker until footnote N, you may need N-1 footnote stubs so that you can skip ahead to the daggers.
The advantage with daggers is threefold: 1) they look cool, and 2) they don’t render properly on all browsers, so you can laugh at people who can’t see them, and 3) you can stab people in the eyes with them if they nitpick! :D
ah my favorite subject, manifests and side by side!
I noticed a recent wizard built app had the following in stdafx.h.
#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:"type=’win32′ name=’Microsoft.Windows.Common-Controls’ version=’6.0.0.0′ processorArchitecture=’x86′ publicKeyToken=’6595b64144ccf1df’ language=’*’"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:"type=’win32′ name=’Microsoft.Windows.Common-Controls’ version=’6.0.0.0′ processorArchitecture=’ia64′ publicKeyToken=’6595b64144ccf1df’ language=’*’"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:"type=’win32′ name=’Microsoft.Windows.Common-Controls’ version=’6.0.0.0′ processorArchitecture=’amd64′ publicKeyToken=’6595b64144ccf1df’ language=’*’"")
#else
#pragma comment(linker,"/manifestdependency:"type=’win32′ name=’Microsoft.Windows.Common-Controls’ version=’6.0.0.0′ processorArchitecture=’*’ publicKeyToken=’6595b64144ccf1df’ language=’*’"")
#endif
#endif
If the last entry accepts the ‘*’ for the processor architecture, why can’t it just be used for all of them?
You get this manifest automatically for some project types. E.g., MFC Applications get them. Can’t remember what others do…
There’s no downside to ‘*’ in this context. There was confusion here about the identity of the component being built (which inherently can’t be ‘*’, it needs to be a specific processor architecture) vs. the component being referenced.
I believe this is being changed in a future release of the libraries; I was on an internal email thread about it recently but there is no harm in the current pattern.
Thanks for the pointer Raymond.
<rant>
I wouldn’t mind the manifest stuff if it wasn’t so mixed in with everything else in the world. As it is, its hard enough to write non-trivial cross-platform code. Now its even harder to write builds/code that run on vc7.1 and vc8.0
Somehow, I’ve managed to do it, but I’ll be damned if I remember what I did.
I think all microsoft headers should have pragma linker directives to simplify life. Then if I am bold enough to create my own new-fangled DLL hell, then its my problem.
</rant>
[Manifests aren’t just a click away already? Surely that’s sort of important. Then again, I am used to Java IDEs where manifests are critically important: maybe they’re optional in C++?]
Umm.. Have you used C++ lately? It is a microsoft extension.
Not to become a dreaded Nitpicker’s Corner nitpicker, but shouldn’t the initial nonfootnote * be followed by a footnote * to denote that the first is not a footnote. Otherwise, the Nitpicker’s Corner statement becomes false.
I do so enjoy the Nitpicker’s corner though. Keep it up.
PingBack from http://www.shugye.com/2007/06/visualcpp-generate-manifest-pragma-35.html
Anthony: it’s mysterious but documented. See <http://msdn2.microsoft.com/En-US/library/aa376617.aspx>
While using the pragma is neat, as Mark K pointed out, there’s no way to add the TrustInfo section.
There’s also no way to add the Description from what I can tell, so instead with VS2005, I’ve gone for adding an include of a file named ccontrols.manifest that looks like this to each of my projects:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<description>My program Description</description>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0"
processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
I then set the Additional Manifest Files option to $(InputDir)ccontrols.manifest on the Manifest Tool property page.
The other thing to watch out for is that you must remember to set the linker options to generate the manifest, and remember to set your assembly identity on the Manifest tool General Tab. I’ve done it thus:
MyCompany.MyProductName.MyFileName, version=$(VersionNumber), processorArchitecture=X86, type=win32
and also used a custom property page to define the version number in one place.
These manifests really have given me a hard time though, with variouus random messages popping up on XP and Vista.
Yesterday was the best, when I accidentally typed in my Identity as:
MyCompany.MyProductName,MyFileName, version=$(VersionNumber), processorArchitecture=X86, type=win32
with a comma before the MyFileName instead of a dot. Here’s what vista said:
"The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log for more detail"
The event log said:
Activation context generation failed for "C:yourapp.exe".Error in manifest or policy file "C:yourapp.exe" on line 1. The attribute typeName is not permitted in this context on element assemblyIdentity.
The other error I made was that I managed to get two manifests into a file, one with resource ID 1 and another with resource ID 2, when I was building my custom bootstrapper tool, because I hadn’t realized that Visual Studio 2005 automatically sets the ID to 2 for DLL projects, and on for exes. When I then copied the resource into my exe to build my custom bootstrapper, I got two copies.
Ugh.
I have to admit I’m a bit confused by which information is used where in all of this. For example which version number is more important? The one in the version resource, or the one in the manifest?
Anthony Wieser
Wieser Software Ltd
Can you use this technique to embed Vista type manifest info, eg the stuff about running as admin etc in old Win32 C++ code?
Mike
Thanks KJK::Hyperion,
I hadn’t found that section of the documentation yet. Looks like another day’s learning.
Thanks for making me laugh!
A perfect example of error recovery.
Question for Raymond (or someone working in VS team):
When I use /MD switch in VS 2005 SP1 I get this:
<?xml version=’1.0′ encoding=’UTF-8′ standalone=’yes’?>
<assembly xmlns=’urn:schemas-microsoft-com:asm.v1′ manifestVersion=’1.0′>
<dependency>
<dependentAssembly>
<assemblyIdentity type=’win32′ name=’Microsoft.VC80.CRT’ version=’8.0.50727.762′ processorArchitecture=’x86′ publicKeyToken=’1fc8b3b9a1e18e3b’ />
</dependentAssembly>
</dependency>
</assembly>
However, when I use /MT switch I get this:
<?xml version=’1.0′ encoding=’UTF-8′ standalone=’yes’?>
<assembly xmlns=’urn:schemas-microsoft-com:asm.v1′ manifestVersion=’1.0′>
</assembly>
Exectuable doesn’t work with /MT — I get runtime error R6034. If I manually embed correct manifest it works fine. Wtf?