Of Static Code Analysis, CA0001, WinMD files and C# Dynamic in Metro Style apps

By jay at October 27, 2012 12:42 Tags: , , , ,

tl;dr: This article is about working around an FxCop internal bug using the C# dynamic keyword, not exactly the way is was supposed to be used.

 

With the release of Windows 8 and WinRT, developing in .NET requires adding references to the new WinMD file format.

This format is a .NET assembly look-alike, so look-alike that old ILDASM builds can open them.

These files are only containing stubs, the definition of types that come from WinRT, which is developed using native C++ code.

 

WinMD files and Static Code Analysis

FxCop is working rather fine with WinMD files in Metro style apps, except for one interest case, when compiling the following code :

private static void SomeMethod()
{
   var b = new Button();
   b.Command = null;
}

Which fails with the following exception when analyzed by FxCop, using the “Microsoft Managed Recommended Rules”:

CA0001 : Rule=Microsoft.Reliability#CA2002, Target=App.MainPage.#SomeMethod() : The following error was encountered while reading module 'App3': Could not resolve member reference: [Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null] Windows.UI.Xaml.Controls.Primitives.ButtonBase::put_Command.

The reason for this is rather obscure though. It seems that FxCop is trying to analyse the declarative security attributes of WinMD exposed methods, but fails to do so… Which is ironic since these attributes cannot be used in Metro style apps :) But still, this is a multi-framework analysis engine.

Unfortunately, there seem to be no way to put an ignore directive, or supression attribute for this kind of internal error so fixing this, until this gets resolved by Microsoft, requires a bit of a hack.

 

A CA0001 workaround and the Dynamic keyword

The problem here is that FxCop tries to analyze the code, and finds the put_Command() method and tries to analyse it. The goal here is to get the code compiled and executable, while having FxCop ignore it.

Here’s how to do it :

private static void SomeMethod()
{
   #if DEBUG
   var b = new Button();
   #else
   dynamic b = new Button();
   #endif

   b.Command = null;
}

I do agree with you, really. This is not a particularly pretty code, and may not be that fast to execute, but it does the trick to still have Static Code Analysis running to catch all other possible code issues.

Having a dynamic variable in Release configuration, where FxCop is executed, allows to hide the call to put_Command() as a string generated by the C# compiler, while maintaining it original meaning.

Here's what actually generated by the compiler, to evade FxCop scrutiny :

object b = new Button();
if (MainPage.o__SiteContainer0.<>p__Site1 == null)
{
   MainPage.o__SiteContainer0.<>p__Site1 = CallSite>.Create(Binder.SetMember(CSharpBinderFlags.None, "Command", typeof(MainPage), new CSharpArgumentInfo[]
   {
      CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
      CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null)
   }));
}
MainPage.o__SiteContainer0.<>p__Site1.Target(MainPage.o__SiteContainer0.<>p__Site1, b, null);

Having the code compiling using an actual static typing in Debug configuration leaves a bit of compile-time type checking, nonetheless.

There should be a connect entry for this soon, if you'd like to follow-up.

Happing dynamic hacking ! :)

A bug in VS2008 Code Analysis, Generics normal and nested classes

By Jerome at April 07, 2008 19:12 Tags: , ,

I've found a few days ago a small bug in the former "FxCop" now renamed Code Analysis part of Visual Studio 2008.

While compiling this little piece of code :


public class Dummy<T> where T : IDisposable
    {
        public T Test
        {
            set
            {
                new NestedDummy<T>(default(T));
            }
        }

        class NestedDummy<U>
        {
            public NestedDummy(U item)
            {
                this.Value = item;
            }

            public U Value { get; private set; }
        }
    }

Which is a trimmed down version of the actual code, I saw a lot of errors like this :

MSBUILD : error : CA0001 : Rule=Microsoft.Reliability#CA2001, Target=ConsoleApplication1.Dummy`1+NestedDummy`1.#.ctor(!1) : The following error was encountered while reading module 'ConsoleApplication1': Could not resolve member reference: ConsoleApplication1.Dummy`1<type parameter.T>+NestedDummy`1<type parameter.U>::set_Value.

This means that for some reason, the Code Analysis tool is unable to parse the metadata to check for some analysis rule. This is not a blocking bug since it does not prevent the build from ending properly, but it displays a lot of error messages, which can be disturbing.

To fix to, I found two solutions : Either move the nested class out of its parents class, or remove the generic constraint on the parent class.

I posted the bug on Microsoft Connect, and I was pleasantly surprised to see that it has already been processed and David Kean from Microsoft wrote that the fix will be available in the next Service Pack of Visual Studio 2008.

Not a big issue but still, nice to see that Connect has an impact.

Using Precompiled Headers

By Jerome at March 01, 2004 11:50 Tags: ,
(How to speed up the C/C++ compilation step with Visual Studio .NET 2003)

Visual C++ Pre compilation feature

Microsoft C/C++ compiler features for a long time now something called Header Precompilation, also known as PCH. You may have already encountered it or used it without knowing it.

The concept is quite simple : Why having to parse header files for each C/C++ file to compile that includes them ? For a given compilation, the header files used will not likely change and even for any subsequent compilations. Standard include files like stdio.h, stdlib.h and many system header files do not need to be parsed at each inclusion.

The C/C++ compiler uses a special set of files (default is stdafx.cpp and stdafx.h) where it can find all the files to precompile, and then reuse these pre-compiled headers in an efficient way in any future compilation. This avoids to recompile all these header files, especially the ones from the STL that can be really huge.


1. Using precompiled headers, the default way

At first, the C/C++ compiler searches for a file named stdafx.cpp and tries to compile it. This file only includes the stdafx.h file. This compilation generates a file called $(ProjectName).pch that will be used by other files being compiled to find pre-compiled symbols quickly.

Any other C/C++ file must then have a line like this one :

#include "stdafx.h"

Be aware that this line must be the very first line of your C/C++ file. Anything that you will place before will be ignored, not even parsed.

2. Using precompiled headers, from scratch

PCH feature can also be activated from a empty project, by adding files one by one. Here is the way to do this.

First, create an empty project and add 3 new files : main.cpp, stdafx.h and stdafx.cpp.

  • File stdafx.h :

    #ifndef __STDAFX_H#define __STDAFX_H#include #include #include #include #endif // __STDAFX_H
    
  • File stdafx.cpp, quite simple :

    #include "stdafx.h"
    
  • File main.cpp, also quite simple :

    #include "stdafx.h"int main(){ std::string myString("Hello, World !"); std::cout << myString.c_str() << std::endl; return 0;}
    
  • Once these files are added in the solution explorer into your C++ project, follow these steps :

  • Select the stdafx.cpp file, right click and select Properties :

    The two fields "Create/Use PCH Through File" and "Precompiled Header File" will be filled automatically.

  • Then select the project item in the solution explorer right click and select Properties :

    The two fields "Create/Use PCH Through File" and "Precompiled Header File" will be filled automatically.

    Note that changing the C/C++ properties for the project propagates them to C/C++ files that have not been customized. Here it is main.cpp, but not stdafx.cpp because we've customized settings in the previous step.

  • After setting all this, the first file to be compiled is stdafx.cpp and then the other files in the project.

    You will see that big projects compile much faster when PCH features is enabled. Also note that you can use multiple precompiled header files in one project, although it is not recommended. If you feel like you need to make multiple PCH files, it is time for you to make a static or a dynamic library.

    SEH et Exceptions en C++

    By Jerome at February 03, 2004 11:49 Tags: ,

    Qui ne s'est pas déja retrouvé devant une horrible boite de dialogue de crash de programme ressemblant à celle ci :

    "The memory cannot be 'written' at 0x404459FF".

    Cette boite de dialogue, bien connue des utilisateurs et développeurs sur Windows, est le résultat d'une exception matérielle, souvent la conséquence d'un problème logiciel comme un deréférencement de pointeur nul. Il existe bien entendu beaucoup raisons pour lesquelles cette boite peut apparaitre comme des Access Violation, Divide By Zero, Invalid Operation, Float Overflow et Underflow, Privileged Instruction,... autant de problèmes potentiels qui peuvent arrêter l'exécution d'un programme. 

    Le C++ met à disposition un mécanisme de gestion des exceptions par l'intermédiaire des mots clés try et catch tout en utilisant le handler par défaut. Ce handler (catch(...)) du mécanisme standard n'est cependant pas le plus intéressant car il ne permet pas d'obtenir le contexte d'exécution du processeur lors de la génération de l'exception, ni d'en savoir la cause.

    Windows met à disposition du développeur une API spécifique permettant d'utiliser le Structured Exception Handling. Cela permet, entre autres, d'afficher une boite de dialogue à l'utilisateur avec un minimum d'informations de debug. Il est également possible d'avoir un StackTrace pour un exécutable en utilisant les informations de debug séparées. Contrairement à une idée recue, il est possible de génerer avec visual studio des informations de debug pour un exécutable optimisé avec /Ox par exemple.

    Le compilateur C++ met à disposition un certain nombre de nouveaux mots clés permettant de protéger une section de code ou bien un programme entier et d'en intercepter les exceptions d'une manière plus efficace. On peut notamment utiliser __try, __except et __finally qui spécifiques au compilateur Microsoft. Cette méthode n'est cependant pas la plus simple à utiliser.

    L'utilisation du SEH ici est couplée à l'utilisation de la librairie imagehlp.dll. Cette librairie permet d'explorer les fichiers de symboles (pdb) pour déterminer par exemple les fonctions trouvées en parcourant la StackFrame.

    Cet article du MSJournal de 1997 ainsi que celui ci, (Oui, oui, 1997...) décrit assez bien le fonctionnement et l'utilisation du SEH au travers de l'utilisation d'une instance de classe en singleton, mais ce mode ne permet pas de rendre simplement la main au dernier handler d'exception présent.

    Dans ce code, un mélange de l'utilisation du SEH et des exceptions du C++ permet de protéger des morceaux de code dans des exceptions C++ standard. L'utilisation de la fonction _set_se_translator permet d'enregistrer une fonction appelée lorsqu'une exception survient et de transformer ces exception Win32 en exceptions C++. L'exemple ici n'est pas parfait puisque l'original est utilisé dans le cadre de la protection d'un programme complet (tout le main en quelque sorte). Il se pourrait qu'une exception SEH lancée en dehors d'un bloc protégé génère tout de même la boite de dialogue de plantage générique.

    Quoi qu'il en soit, l'utilisation de ce code est assez simple, il faut juste noter qu'il est nécessaire d'activer la génération des StackFrames (désactiver Omit Stack Frames) ainsi que des informations de debug sous forme de fichier extérieur (Debug Information Format : Program Database). Il faut noter également qu'il est indispensable de distribuer le fichier imagehlp.dll et les fichiers pdb (Program Database) avec l'executable pour avoir l'affichage de la StackTrace lors d'une exception.

    Bien entendu pour la distribution publique d'un programme, on ne publiera pas les fichiers pdb, qui contiennent énormément d'informations.

    Il faut noter également qu'il est possible d'utiliser le SEH sous sa forme "native", en C. Vous aurez simplement à supprimer les fonctionnalités spécifique au C++ du code précédent. (Je donne l'info puisque certains utilisent encore ce langage... :p)

    Bon debug !

    About me

    My name is Jerome Laban, I am a Software Architect, C# MVP and .NET enthustiast from Montréal, QC. You will find my blog on this site, where I'm adding my thoughts on current events, or the things I'm working on, such as the Remote Control for Windows Phone.