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:
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.
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.
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.
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++
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.
Abra o arquivo TestVCProjectPropertiesPackage.cs. Adicione estas diretivas using:
using EnvDTE; using EnvDTE80; using System.Windows.Forms; using Microsoft.VisualStudio.VCProjectEngine;
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)); } }
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 } }
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"); } }
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")); } }
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++
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")); } } } }
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.
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
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); }
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); }
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.