Partilhar via


Trabalhando com propriedades do projeto Visual C++

Veja como usar as interfaces do Microsoft.VisualStudio.VCProjectEngine.dll, em especial IVCRulePropertyStorage, para obter e definir propriedades de projeto e itens de projeto do Visual C++. Recomendamos que você use essas interfaces porque as propriedades de projeto do Visual C++ não estão disponíveis no GetProperty e não há garantia de que sejam estáveis em todas as versões.

As propriedades de projeto do Visual C++ estão definidas nos arquivos em %ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V120\1033\. Por exemplo, o arquivo general.xml contém as propriedades gerais do projeto, o debugger_general.xml contém propriedades gerais do depurador e assim por diante. Você pode usar a interface IVCRulePropertyStorage para ler e gravar apenas essas propriedades para os arquivos existentes.

Você define e obtém as propriedades de itens de projeto do Visual C++ a partir da propriedade Tool.

Diferentes tipos de item de arquivo têm diferentes conjuntos de propriedades. Para encontrar o tipo de item de um arquivo no Gerenciador de Soluções do Visual Studio, abra o menu de atalho do arquivo e clique em Propriedades. Por exemplo, o tipo de item de um arquivo .cpp é exibido como compilador do C/C++. Veja como encontrar todas as propriedades de um determinado tipo de item:

  1. Procure o nome de exibição do tipo de item no diretório %ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V120\1033\. Por exemplo, se você procurar por "compilador C/C++", o arquivo ProjectItemsSchema.xml mostra que o nome do tipo de item correspondente é ClCompile.

  2. Para encontrar o arquivo de regras para esse tipo de item, procure no mesmo diretório. (Nesse caso, como o ClCompile aparece em muitos arquivos .targets e .props não relacionados você pode restringir a sua pesquisa a arquivos .xml.) O arquivo de regras para o tipo de item ClCompile é cl.xml.

  3. Procure o arquivo de regras para a propriedade que você deseja encontrar. Por exemplo, a propriedade que tem o nome de exibição Diretórios de Inclusão Adicionais tem o nome de propriedade AdditionalIncludeDirectories.

  4. O arquivo de regras também determina onde uma determinada propriedade é persistente. As propriedades associadas com o tipo de item ClCompile persistem no arquivo do projeto. (Procure o atributo Persistence.) Os valores de propriedades que você altera persistem no arquivo de projeto.

Para obter informações sobre como usar e estender as páginas de propriedades do Visual C++, consulte os seguintes artigos. Eles mencionam o Visual Studio 2010, mas as informações sobre as propriedades de projeto são válidas.

Para observar como o seguinte código funciona, você pode integrá-lo a um VSPackage chamado TestVCProjectProperties que tem um comando de menu chamado Test Project Properties. Para obter informações sobre como fazer isso, consulte Passo a passo: Criando um comando de Menu usando o modelo de pacote de Visual Studio.

Obtendo e definindo propriedades de projeto do Visual C++

  1. Na caixa de diálogo Propriedades do Projeto, na guia Extensões, adicione uma referência para Microsoft.VisualStudio.VCProjectEngine, e na guia Estrutura, adicione uma referência para System.Windows.Forms.

  2. Abra o arquivo TestVCProjectPropertiesPackage.cs. Adicione estas diretivas using:

    using EnvDTE;
    using EnvDTE80;
    using System.Windows.Forms;
    using Microsoft.VisualStudio.VCProjectEngine;
    
  3. Adicione uma referência para o objeto do aplicativo, neste caso DTE2, à classe TestVCProjectPropertiesPackage, e crie uma instância dele no método 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. Remova o código existente do método MenuItemCallback. Adicione código para obter os projetos abertos. Certifique-se de que um projeto esteja realmente aberto.

    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. Obtenha o primeiro projeto e encontre a configuração de projeto com o nome 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. Nesta etapa, você obtém a propriedade IncludePath da regra ConfigurationDirectories e adiciona D:\Include ao valor atual.

    Dica

    Você pode usar um dos dois métodos para obter os valores de propriedade.O método GetUnevaluatedPropertyValue obtém o valor sem avaliar nenhuma propriedade, por exemplo, $(SolutionDir) e o método GetEvaluatedPropertyValue expande essas propriedades.

    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. Compile a solução e inicie a depuração. A compilação aparece em uma segunda instância do Visual Studio conhecida como a instância experimental. Abra um projeto do Visual C++ na instância experimental. Na barra de menus, clique em Ferramentas, Propriedades do Projeto de Teste. Uma caixa de diálogo mostra o valor $(VC_IncludePath);$(WindowsSDK_IncludePath);D:\Include;D:\Include;.

Obtendo e definindo propriedades de itens de projeto do Visual C++

  1. No projeto TestVCProjectProperties que você criou no procedimento anterior, vá para o método MenuItemCallback. Adicione o código a seguir para encontrar um arquivo .cpp no ​​projeto, obtenha a propriedade Diretórios de Inclusão Adicionais e configure-a para D:\Include e exiba uma caixa de diálogo que mostra o novo valor:

    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. Compile a solução e inicie a depuração. Abra um projeto do Visual C++ na instância experimental. Na barra de menus, clique em Ferramentas, Propriedades do Projeto de Teste. Uma caixa de diálogo mostra o valor $(VC_IncludePath);$(WindowsSDK_IncludePath);D:\Include;D:\Include; e uma segunda caixa de diálogo mostra o valor D:\Include.

  3. Para examinar onde esse valor persiste, salve todos os arquivos no projeto aberto na instância experimental. O novo valor aparece no arquivo .vcxproj.

Detectando alterações de valor da propriedade

  1. Você pode assinar o evento ItemPropertyChange2 para detectar quando uma propriedade de projeto ou propriedade de item de projeto do Visual C++ obtiver um valor diferente.

    Na classe TestVCProjectPropertiesPackage, crie um manipulador de eventos para esse evento. Nesse caso, o manipulador exibe apenas uma caixa de diálogo que mostra a propriedade que foi alterada.

    void OnVCProjectEngineItemPropertyChange(Object item, string strPropertySheet, string strItemType, string PropertyName)
    {
        MessageBox.Show("got property change event for " + PropertyName);
    }
    
  2. No método Initialize, obtenha o VCProjectEngineEventsObject dos eventos do objeto do aplicativo e adicione o manipulador de eventos que você acabou de criar:

    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. Compile a solução e inicie a depuração. Abra um projeto do Visual C++ na instância experimental. Na barra de menus, clique em Ferramentas, Propriedades do Projeto de Teste. Uma caixa de diálogo mostra $(VC_IncludePath);$(WindowsSDK_IncludePath);D:\Include;D:\Include;, uma segunda caixa de diálogo mostra Evento de alteração da propriedade obtido para IncludePath, uma terceira caixa de diálogo mostra D:\Include e uma quarta caixa de diálogo mostra Evento de alteração da propriedade obtido para AdditionalIncludeDirectories.

    Dica

    Você não obterá o evento de alteração da propriedade depois que as alterações deste código persistirem.Para ver o evento, altere o valor da propriedade para algo diferente.