Posts mit dem Label Manifest werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Manifest werden angezeigt. Alle Posts anzeigen

Donnerstag, 24. März 2011

Enabling Visual Styles - Make it pretty!

Hello there

A lot of people ask me why in C++ the windows they create look that ugly while in C# or other .NET languages they look very nice. To illustrate what i mean look at the following images:
C++:


C#


The reason why this happens lies inside the manifest (or more exactly the application context). A .NET application automatically generates an application context that loads the Version 6 of the Microsoft.Windows.Common-Controls assembly instead of the default one which is Version 5. While Version 5 renders the common controls without any visual styles Version 6 uses the appropriate styles since Windows XP.

To achieve that you need to add a dependency inside the manifest and you need to ship it with your executable. Thats how the source code looks in my example application which is the way i prefer to ship the manifest with my application.
#include <windows.h>
#include "resource.h"

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;
 case WM_INITDIALOG:
  return TRUE;
 }

 return FALSE;
}

int main()
{
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

IDD_DIALOG1 is the numerical constant of a dialog resource embedded inside my executable.

Thanks for reading and im looking forward reading your comments!
Yanick

Shipping Manifests

Hello there

In this article we will have a look how to ship a manifest with your application. If you need to know what a manifest is please reference to this article.

There are different ways to deploy a manifest with your application. I will refer on how to achieve it using the Microsoft IDE (either for C# or C++ respectively).
  1. In C++ you can directly modify the default manifest using a #pragma directive or the project settings
  2. In C++ you can directly create a manifest as a resource of your application
  3. In C# you have to possibility to add a manifest as a project object and select it as default one
  4. For every component you can ship the manifest as separate file (not recommended!)
Now lets explain this a bit more:

Modify the default manifest 
To modify the manifest directly inside your code you can use the #pragma comment(linker, "...") directive. This is an example how this would look like:

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

This adds a dependent assembly to the manifest (reference article linked above if you need to know what a dependent assembly is). The same can also be achieved if you go to your project properties. There in the category linker you find the property page "Manifest file". This looks like the following:



There you can modify the manifest as you like to.

Add a manifest resource
Adding a manifest as a resource is very easy. You can simply create your manifest as you like and add it to the executable with resource type RT_MANIFEST or 24. Its recommended that you choose the name taken in the assemblyIdentity part inside the manifest followed by .manifest as name of the resource. Thats it!


Add a manifest inside C#Adding manifests in C# is even simpler. Right click into your project and choose Add -> New Item. In the dialog scroll down until you find "Application manifest file" and give it a name. It creates the default entries and lists it in the solution explorer. You can now edit the manifest inside the editor. If you want to make your manifest the default one visit the project settings and go to the "Application" tab. There you find a region with "Resources" which contains a drop down list with possible manifest files to use. Thats it!

So adding manifests is a very easy thing to do and its worth it ;)

Thanks for reading and goodbye
Yanick 

Manifests - Lets declare some principles!

Hello again!

In this article I like to spend a few words on a concept introduced with Windows XP: Manifest files. These files are used beside an executable to tell various things about the context the program will run in. I think the most common usage of manifests is to enable visual styles in an application. But if we look closer on that we can see that it actually is not like manifests directly enable the visual styles, no, the manifest actually only tells the operating system that our application depends on a so called 'assembly'. Don't be scared, it has nothing to do with assembler, ill explain later what to understand under assemblies and what dependency means.

So we have learned one important aspect of manifests:
  • They can declare dependencies to assemblies.
Ok, but ask yourself: Did you ever find a manifest in programming world yet? I bet no if you didn't intend to ;). So  is no one using manifests or what is the reason for that? No, id say every executable you start is using a manifest, but where is it? To answer that question you need to know how the operating system actually searches for that manifest.
  1. It searches in the global cache.
  2. It searches for the first resource inside the executable which has the type RT_MANIFEST (24 on my system) 
  3. If nothing is found inside the exe it searches inside the folder if it finds a file named EXENAME.exe.manifest.
Because modifying a manifest without knowledge about it by an end user may result in severe problems running the application the third method isn't chosen often by deployed programs. As modifying resources at least requires the knowledge how to access and compile resources into a file you can be pretty sure that most users of your application wont be able to accidentally destroy the manifest (and if they do its not our problem :D). Thats the reason why you probably have never seen a manifest file - they are inside the executable!

Well, i think its time now to have a view on an example manifest. If you create a new project in Visual Studio a manifest is automatically generated when you build your application. It can be found inside the Debug (or Release) folder of your project (not solution) and is called 'ProjectName.exe.intermediate.manifest'. It has the intermediate inside it because thats the part that gets automatically added but you can modify that inside the project settings and thus its not the final version but only an intermediate one.

I named my Project ManifestExample so the manifest is called ManifestExample.exe.intermediate.manifest and the contents are:
<assembly manifestversion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <trustinfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedprivileges>
        <requestedexecutionlevel level="asInvoker" uiaccess="false">
      </requestedexecutionlevel>
    </security>
  </trustinfo>
</assembly> 

First thing we see is that manifests are written using the XML syntax. That makes it pretty straightforward to understand and we can focus on the actual elements. What this manifest does is that it defines some security related properties of the application. To be more clear: It declares which access rights the user has to have this application will run in. That is controlled using the 'level' attribute inside the requestedexecutionlevel tag. There are 3 values valid for the level attribute:
  1. asInvoker -> The application will run with the same privileges as the calling user
  2. highestAvailable -> The application will run with the highest privileges the current user can reach
  3. requireAdministrator -> The application must be run in administrator mode (on Vista and Win7 a window will pop up asking the user to allow the application to run as administrator if thats enabled)
The default value of course is asInvoker as thats pretty neutral.

The uiaccess attribute is a bit more complex. Imagine you are writing an application that simulates a keyboard on the monitor where the user can make input. Now it may be necessary to bypass regular input control mechanics to work properly. To be able to do that the uiaccess attribute must be set to true.

In addition setting uiaccess to true requires some additional security options! The application first has to be signed by Authenticode and second it has to be in protected folder (for example system32 or program files).

Second thing we learned about manifests:
  • Manifests define security aspects of an application.
Now lets have a look at a manifest that does what i ment above: Add a dependency to an executable. In this example we add a dependency to the assembly called "CommonControls". It has to be said that your application be default already has a dependency to CommonControls but it depends on version 5 of CommonControls which contains the old visual themes and we need version 6 which contains the new visual themes since XP!

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>

  <dependency>
    <dependentAssembly>
      <assemblyIdentity 
        type='win32' 
        name='Microsoft.Windows.Common-Controls'
        version='6.0.0.0' 
        processorArchitecture='*'
        publicKeyToken='6595b64144ccf1df'
        language='*'
      />
    </dependentAssembly>
  </dependency>
</assembly>


The new tags we see are dependency, dependentAssembly, assemblyIndentity. The dependency tag lists a dependency for application the dependentAssembly tag hosts a dependency to an assembly and the assemblyIndentity tag finally specifies the assembly our application is depending from. There we find several possible attributes that identify the assembly. Actually only two of them are required the rest is optional and is used to distinguish it from other assemblies that may have the same attributes.

Explanation:
  • type - Optional - Only valid value is win32
  • name - Required - The name of the assembly
  • version - Required - The version of the assembly to load
  • processorArchitectur - Optional - May be clear. Valid values are (ia64, amd64, x86, msil)
  • publicKeyToken - Optional - The strong name of the assembly
  • language - Optional - The language ID of the assembly
As you can see we request version 6 of the Common-Controls which means controls with new visual styles!

Now its time to talk about how the system finds an assembly. This is actually pretty simple. The system does the same as it does when you launch an application. In the above code it will search a manifest which denotes an assembly witch defines an assemblyIdentity that matches the requested one. In our case it searches the following way:
  1. It searches the Microsoft.Windows.Common-Controls.dll inside global search paths and inside the current executables path. If it finds that dll it searches a manifest resource inside that dll that is called "Microsoft.Windows.Common-Controls.manifest" and compares it.
  2. If that didnt succeed the system searches in the same paths for a file called Microsoft.Windows.Common-Controls.manifest and parses it
  3. If that failed it searches for the folder "Microsoft.Windows.Common-Controls" inside all global search paths and the current executable path and does the same search as above again
To be identified a component (for example a DLL) must have a manifest that defines a global assemblyIdentity. That actually makes it an recognizable assembly inside the system. Here is an example manifest that identifies everything its included into as an assembly of the given name (and does nothing more):


      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <assembly xmlns="urn:schemas-microsoft-com:asm.v1"  manifestVersion="1.0">
        <assemblyIdentity
          type="Win32"
          name="MyNiceAssembly"
          version="1.0.0.0" 
        />
      </assembly>
      

      We learn:
      • Manifests can be used to give any component (DLL, exe, ...) a name with which it can be identified
      Thats it for this article! Feel free to post comments or ask questions. I dont think that everything got clear enough for everyone so im really happy if you tell me your problems or questions!

      Thanks
      Yanick