Utilisation des propriétés de projets Visual C++

Voici comment utiliser les interfaces dans Microsoft.VisualStudio.VCProjectEngine.dll, en particulier IVCRulePropertyStorage, pour obtenir et définir les propriétés d'un projet Visual C++ ainsi que les propriétés des éléments de projet. Nous vous recommandons d'utiliser ces interfaces car les propriétés de projet Visual C++ ne sont pas disponibles via la méthode GetProperty et leur stabilité n'est pas garantie d'une version à l'autre.

Les propriétés de projet Visual C++ sont définies dans les fichiers sous %ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V120\1033\. Par exemple, general.xml contient des propriétés de projet générales, debugger_general.xml contient des propriétés de débogage générales, etc. Vous pouvez utiliser l'interface IVCRulePropertyStorage pour lire et écrire uniquement ces propriétés pour lesquelles l'un de ces fichiers existe.

Vous définissez et obtenez les propriétés des éléments de projet Visual C++ à partir de la propriété Tool.

Les différents types d'éléments de fichier comportent divers ensembles de propriétés. Pour rechercher le type d'élément d'un fichier dans l'Explorateur de solutions, ouvrez le menu contextuel de votre projet, puis choisissez Propriétés. Par exemple, le type d'élément d'un fichier .cpp est affiché en tant que Compilateur C/C++. Voici comment rechercher toutes les propriétés d'un type d'élément donné :

  1. Recherchez le nom d'affichage du type d'élément dans le répertoire %ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V120\1033\. Par exemple, si vous recherchez « Compilateur C/C++ », le fichier ProjectItemsSchema.xml montre que le nom du type d'élément correspondant est ClCompile.

  2. Pour trouver le fichier de règles de ce type d'élément, recherchez-le dans le même répertoire. (Dans ce cas, vous pouvez limiter votre recherche aux fichiers .xml. car ClCompile apparaît dans de nombreux fichiers .targets et .props non liés) Le fichier de règles du type d'élément ClCompile est cl.xml.

  3. Recherchez le fichier de règles de la propriété qui vous intéresse. Par exemple, la propriété au nom complet Autres répertoires Include a le nom de propriété AdditionalIncludeDirectories.

  4. Le fichier de règles détermine aussi l'emplacement où une propriété donnée est persistante. Les propriétés associées au type d'élément ClCompile sont persistantes dans le fichier projet. (Recherchez l'attribut Persistence.) Les valeurs de propriété que vous modifiez sont persistantes dans le fichier projet.

Pour plus d'informations sur l'utilisation et l'extension des pages de propriétés Visual C++, consultez les articles suivants. Ils portent sur Visual Studio 2010, mais les informations sur les propriétés de projet continuent de s'appliquer.

Pour observer le fonctionnement du code suivant, vous pouvez l'intégrer à un VSPackage intitulé TestVCProjectProperties qui comporte une commande de menu nommée Test Project Properties. Pour plus d'informations sur la procédure à suivre, consultez Procédure pas - à - pas : Créer une commande de menu à l'aide de le modèle de package Visual Studio.

Obtention et définition des propriétés de projet Visual C++

  1. Dans la boîte de dialogue Propriétés de projet, sous l'onglet Extensions, ajoutez une référence à Microsoft.VisualStudio.VCProjectEngine, puis sous l'onglet Framework, ajoutez une référence à System.Windows.Forms.

  2. Ouvrez le fichier TestVCProjectPropertiesPackage.cs. Ajoutez ces directives using :

    using EnvDTE;
    using EnvDTE80;
    using System.Windows.Forms;
    using Microsoft.VisualStudio.VCProjectEngine;
    
  3. Ajoutez une référence à l'objet Application (dans ce cas, DTE2) à la classe TestVCProjectPropertiesPackage, puis instanciez-le dans la méthode Initialize :

    public sealed class TestProjectPropertiesPackage : Package
    {
        DTE2 dte2;
        . . .
        protected override void Initialize()
        {
            Debug.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
            base.Initialize();
    
            // Add command handlers for the menu (commands must exist in the .vsct file)
            OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
            if ( null != mcs )
            {
                // Create the command for the menu item.
                CommandID menuCommandID = new CommandID(GuidList.guidTestProjectPropertiesCmdSet, (int)PkgCmdIDList.cmdidMyCommand);
                MenuCommand menuItem = new MenuCommand(MenuItemCallback, menuCommandID );
                mcs.AddCommand( menuItem );
            }
    
            dte2 = (DTE2)GetService(typeof(DTE));
        }
    }
    
  4. Supprimez le code existant de la méthode MenuItemCallback. Ajoutez du code pour obtenir les projets ouverts. Vérifiez qu'un projet est réellement ouvert.

    private void MenuItemCallback(object sender, EventArgs e) 
    {
        VCProject prj; 
        Projects projColl = dte2.Solution.Projects; 
    
        if (projColl.Count == 0) 
        {
            MessageBox.Show("You must have a project open in the experimental instance."); 
            return; 
        }
        if (projColl.Count > 0) 
        {
            // To be filled in later
        }
    }
    
  5. Obtenez le premier projet et recherchez la configuration de projet nommée Win32|Debug :

    private void MenuItemCallback(object sender, EventArgs e) 
    {
        VCProject prj; 
        Projects projColl = dte2.Solution.Projects; 
    
        if (projColl.Count == 0) 
        {
            MessageBox.Show("You must have a project open in the experimental instance."); 
            return; 
        }
        if (projColl.Count > 0) 
        {
            prj = (VCProject)dte2.Solution.Projects.Item(1).Object;
             VCConfiguration config = prj.Configurations.Item("Debug|Win32");
        }
    }
    
  6. Dans cette étape, vous obtenez la propriété IncludePath à partir de la règle ConfigurationDirectories et ajoutez D:\Include à la valeur actuelle.

    Notes

    Vous pouvez utiliser l'une des deux méthodes pour obtenir les valeurs de propriété.La méthode GetUnevaluatedPropertyValue obtient la valeur sans analyser les propriétés (par exemple, $(SolutionDir)) et la méthode GetEvaluatedPropertyValue développe ces propriétés.

    private void MenuItemCallback(object sender, EventArgs e) 
    {
        VCProject prj; 
        Projects projColl = dte2.Solution.Projects; 
    
        if (projColl.Count == 0) 
        {
            MessageBox.Show("You must have a project open in the experimental instance."); 
            return; 
        }
        if (projColl.Count > 0) 
        {
            prj = (VCProject)dte2.Solution.Projects.Item(1).Object;
             VCConfiguration config = prj.Configurations.Item("Debug|Win32");
    
             IVCRulePropertyStorage rule = config.Rules.Item("ConfigurationDirectories") as IVCRulePropertyStorage;
             string rawValue = rule.GetUnevaluatedPropertyValue("IncludePath");
             string evaluatedValue = rule.GetEvaluatedPropertyValue("IncludePath");
             rule.SetPropertyValue("IncludePath", rawValue + "D:\\Include;");
    
             // Get the new property value
             MessageBox.Show(rule.GetUnevaluatedPropertyValue("IncludePath"));
        }
    }
    
  7. Générez la solution et commencez le débogage. La build apparaît dans une seconde instance de Visual Studio réputée comme étant l'instance expérimentale. Ouvrez un projet Visual C++ dans l'instance expérimentale. Dans la barre de menus, choisissez Outils, Test Project Properties. Une boîte de dialogue affiche la valeur $(VC_IncludePath);$(WindowsSDK_IncludePath);D:\Include;D:\Include;.

Obtention et définition des propriétés des éléments de projet Visual C++

  1. Dans le projet TestVCProjectProperties que vous avez créé au cours de la procédure précédente, accédez à la méthode MenuItemCallback. Ajoutez le code suivant pour rechercher un fichier .cpp dans le projet, obtenez la propriété Autres répertoires Include et affectez-lui la valeur D:\Include, puis affichez une boîte de dialogue qui laisse apparaître la nouvelle valeur :

    private void MenuItemCallback(object sender, EventArgs e)
    {
        VCProject prj;
        Projects projColl = dte2.Solution.Projects;
    
        if (projColl.Count == 0)
        {
            MessageBox.Show("You must have a project open in the experimental instance.");
            return;
        }
        if (projColl.Count > 0)
        {
            prj = (VCProject)dte2.Solution.Projects.Item(1).Object;
    
            VCConfiguration config = prj.Configurations.Item("Debug|Win32");
            IVCRulePropertyStorage rule = config.Rules.Item("ConfigurationDirectories") as IVCRulePropertyStorage;
             string rawValue = rule.GetUnevaluatedPropertyValue("IncludePath");
             string evaluatedValue = rule.GetEvaluatedPropertyValue("IncludePath");
             rule.SetPropertyValue("IncludePath", rawValue + "D:\\Include;");
    
             // Get the new property value
             MessageBox.Show(rule.GetUnevaluatedPropertyValue("IncludePath"));
    
            foreach (VCFile file in prj.Files)
            {
                if (file.FileType == eFileType.eFileTypeCppCode)
                {
                    VCFileConfiguration fileConfig = file.FileConfigurations.Item("Debug|Win32") as VCFileConfiguration;
                    IVCRulePropertyStorage fileRule = fileConfig.Tool as IVCRulePropertyStorage;
                    string evaluatedValue2 = fileRule.GetEvaluatedPropertyValue("AdditionalIncludeDirectories");
                    fileRule.SetPropertyValue("AdditionalIncludeDirectories", "D:\\Include");
                    MessageBox.Show(fileRule.GetEvaluatedPropertyValue("AdditionalIncludeDirectories"));
                }
            }  
        }
    }
    
  2. Générez la solution et commencez le débogage. Ouvrez un projet Visual C++ dans l'instance expérimentale. Dans la barre de menus, choisissez Outils, Test Project Properties. Une boîte de dialogue affiche la valeur $(VC_IncludePath);$(WindowsSDK_IncludePath);D:\Include;D:\Include tandis qu'une seconde boîte de dialogue affiche la valeur D:\Include.

  3. Pour examiner l'emplacement où la valeur est persistante, enregistrez tous les fichiers dans le projet ouvert de l'instance expérimentale. La nouvelle valeur apparaît dans le fichier .vcxproj.

Détection des modifications de la valeur d'une propriété

  1. Vous pouvez vous abonner à l'événement ItemPropertyChange2 pour détecter quand une propriété de projet Visual C++ ou une propriété d'élément de projet obtient une autre valeur.

    Dans la classe TestVCProjectPropertiesPackage, créez un gestionnaire d'événements pour cet événement. Dans ce cas, le gestionnaire affiche simplement une boîte de dialogue montrant la propriété qui a été modifiée.

    void OnVCProjectEngineItemPropertyChange(Object item, string strPropertySheet, string strItemType, string PropertyName)
    {
        MessageBox.Show("got property change event for " + PropertyName);
    }
    
  2. Dans la méthode Initialize, obtenez le VCProjectEngineEventsObject depuis les événements de l'objet Application, puis ajoutez le gestionnaire d'événements que vous venez de créer :

    protected override void Initialize()
    {
        Debug.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
        base.Initialize();
    
        // Add the command handlers for the menu (commands must exist in the .vsct file)
        OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
        if ( null != mcs )
        {
            // Create the command for the menu item
             CommandID menuCommandID = new CommandID(GuidList.guidTestProjectPropertiesCmdSet, (int)PkgCmdIDList.cmdidMyCommand);
            MenuCommand menuItem = new MenuCommand(MenuItemCallback, menuCommandID );
            mcs.AddCommand( menuItem );
        }
    
        dte2 = (DTE2)GetService(typeof(DTE));
        VCProjectEngineEvents vcProjectEvents = dte2.Events.GetObject("VCProjectEngineEventsObject") as VCProjectEngineEvents;
    
        vcProjectEvents.ItemPropertyChange2 += new _dispVCProjectEngineEvents_ItemPropertyChange2EventHandler(OnVCProjectEngineItemPropertyChange);
    }
    
  3. Générez la solution et commencez le débogage. Ouvrez un projet Visual C++ dans l'instance expérimentale. Dans la barre de menus, choisissez Outils, Test Project Properties. Une boîte de dialogue affiche la valeur $(VC_IncludePath);$(WindowsSDK_IncludePath);D:\Include;D:\Include;, une deuxième boîte de dialogue affiche Got property change event for IncludePath, une troisième affiche D:\Include et une quatrième affiche Got property change event for AdditionalIncludeDirectories.

    Notes

    Vous n'obtiendrez pas l'événement de modification de propriété après la persistance des modifications dans ce code.Pour voir l'événement, remplacez la valeur de propriété par une autre valeur.