Criar um sistema de projeto básico, parte 1
No Visual Studio, projetos são os contêineres que os desenvolvedores usam para organizar arquivos de código-fonte e outros ativos. Os projetos aparecem como filhos de soluções no Gerenciador de Soluções. Os projetos permitem organizar, compilar, depurar e implantar código-fonte e criar referências a serviços Web, bancos de dados e outros recursos.
Projetos são definidos em arquivos de projeto, por exemplo, um arquivo .csproj para um projeto Visual C#. Você pode criar seu próprio tipo de projeto que tenha sua própria extensão de nome de arquivo de projeto. Para obter mais informações sobre tipos de projeto, consulte Tipos de projeto.
Observação
Se você precisar estender o Visual Studio com um tipo de projeto personalizado, é altamente recomendável aproveitar o sistema de projeto do Visual Studio (VSPS), que tem várias vantagens sobre a criação de um sistema de projeto do zero:
Integração mais fácil. Mesmo um sistema de projeto básico requer dezenas de milhares de linhas de código. O aproveitamento do VSPS reduz o custo de integração a alguns cliques antes que você esteja pronto para personalizá-lo de acordo com suas necessidades.
Manutenção mais fácil. Ao aproveitar o VSPS, você só precisa manter seus próprios cenários. Nós cuidamos da manutenção de toda a infraestrutura do sistema do projeto.
Se você precisar direcionar versões do Visual Studio mais antigas que o Visual Studio 2013, você não poderá aproveitar o VSPS em uma extensão do Visual Studio. Se esse for o caso, este passo a passo é um bom lugar para começar.
Este passo a passo mostra como criar um tipo de projeto que tenha a extensão de nome de arquivo de projeto .myproj. Este passo a passo pega emprestado do sistema de projeto Visual C# existente.
Observação
Para obter mais exemplos de projetos de extensão, consulte Exemplos de VSSDK.
Este passo a passo ensina como realizar estas tarefas:
Crie um tipo de projeto básico.
Crie um modelo de projeto básico.
Registre o modelo de projeto com o Visual Studio.
Crie uma instância de projeto abrindo a caixa de diálogo Novo Projeto e usando seu modelo.
Crie uma fábrica de projetos para seu sistema de projeto.
Crie um nó de projeto para seu sistema de projeto.
Adicione ícones personalizados para o sistema do projeto.
Implemente a substituição básica de parâmetros de modelo.
Pré-requisitos
Baixe o código-fonte do Managed Package Framework para projetos. Extraia o arquivo para um local acessível à solução que você vai criar.
Criar um tipo de projeto básico
Crie um projeto C# VSIX chamado SimpleProject. (Arquivo>Novo>Projeto e, em seguida, Visual C#>Extensibility>VSIX Project). Adicione um modelo de item de projeto do Pacote do Visual Studio (no Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto e selecione Adicionar>Novo Item e vá para Extensibilidade>do Pacote do Visual Studio). Nomeie o arquivo SimpleProjectPackage.
Criando um modelo de projeto básico
Agora, você pode modificar esse VSPackage básico para implementar o novo tipo de projeto .myproj . Para criar um projeto baseado no tipo de projeto .myproj, o Visual Studio precisa saber quais arquivos, recursos e referências adicionar ao novo projeto. Para fornecer essas informações, coloque arquivos de projeto em uma pasta de modelo de projeto. Quando um usuário usa o projeto .myproj para criar um projeto, os arquivos são copiados para o novo projeto.
Para criar um modelo de projeto básico
Adicione três pastas ao projeto, uma sob a outra: Templates\Projects\SimpleProject. (Em Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto SimpleProject , aponte para Adicionar e clique em Nova Pasta. Nomeie a pasta Modelos. Na pasta Modelos , adicione uma pasta chamada Projetos. Na pasta Projetos , adicione uma pasta chamada SimpleProject.)
Na pasta Templates\Projects\SimpleProject, adicione um arquivo de imagem de bitmap para usar como o ícone chamado SimpleProject.ico. Quando você clica em Adicionar, o editor de ícones é aberto.
Torne o ícone distinto. Esse ícone aparecerá na caixa de diálogo Novo Projeto posteriormente na explicação passo a passo.
Salve o ícone e feche o editor de ícones.
Na pasta Templates\Projects\SimpleProject, adicione um item de classe chamado Program.cs.
Substitua o código existente pelas seguintes linhas.
using System; using System.Collections.Generic; using System.Text; namespace $nameSpace$ { public class $className$ { static void Main(string[] args) { Console.WriteLine("Hello VSX!!!"); Console.ReadKey(); } } }
Importante
Esta não é a forma final do código .cs Programa, os parâmetros de substituição serão tratados em uma etapa posterior. Você pode ver erros de compilação, mas contanto que BuildAction do arquivo seja Content, você deve ser capaz de compilar e executar o projeto como de costume.
Salve o arquivo.
Copie o arquivo AssemblyInfo.cs da pasta Properties para a pasta Projects\SimpleProject .
Na pasta Projects\SimpleProject, adicione um arquivo XML chamado SimpleProject.myproj.
Observação
A extensão de nome de arquivo para todos os projetos desse tipo é .myproj. Se você quiser alterá-lo, você deve alterá-lo em todos os lugares que é mencionado no passo a passo.
Substitua o conteúdo existente pelas seguintes linhas.
<?xml version="1.0" encoding="utf-8" ?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid></ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>MyRootNamespace</RootNamespace> <AssemblyName>MyAssemblyName</AssemblyName> <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <DebugSymbols>true</DebugSymbols> <OutputPath>bin\Debug\</OutputPath> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <DebugSymbols>false</DebugSymbols> <OutputPath>bin\Release\</OutputPath> </PropertyGroup> <ItemGroup> <Reference Include="mscorlib" /> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="AssemblyInfo.cs"> <SubType>Code</SubType> </Compile> <Compile Include="Program.cs"> <SubType>Code</SubType> </Compile> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </Project>
Salve o arquivo.
Na janela Propriedades, defina a Ação de compilação de AssemblyInfo.cs, Program.cs, SimpleProject.ico e SimpleProject.myproj como Conteúdo e defina suas propriedades Include in VSIX como True.
Este modelo de projeto descreve um projeto básico do Visual C# que tem uma configuração de depuração e uma configuração de versão. O projeto inclui dois arquivos de código-fonte, AssemblyInfo.cs e Program.cs, e várias referências de assembly. Quando um projeto é criado a partir do modelo, o valor ProjectGuid é substituído automaticamente por um novo GUID.
No Gerenciador de Soluções, a pasta Modelos expandida deve aparecer da seguinte maneira:
Templates
Projects
SimpleProject
AssemblyInfo.cs
Program.cs
SimpleProject.ico
SimpleProject.myproj
Criar uma fábrica de projeto básico
Você deve informar ao Visual Studio o local da pasta de modelo de projeto. Para fazer isso, adicione um atributo à classe VSPackage que implementa a fábrica do projeto para que o local do modelo seja gravado no registro do sistema quando o VSPackage for criado. Comece criando uma fábrica de projeto básica que é identificada por um GUID de fábrica de projeto. Use o ProvideProjectFactoryAttribute atributo para conectar a fábrica do projeto à SimpleProjectPackage
classe.
Para criar uma fábrica de projetos básicos
Crie GUIDs para a fábrica do projeto (no menu Ferramentas , clique em Criar GUID) ou use o do exemplo a seguir. Adicione os GUIDs à classe próxima à
SimpleProjectPackage
seção com oPackageGuidString
arquivo . Os GUIDs devem estar no formato GUID e no formato string. O código resultante deve ser semelhante ao exemplo a seguir.public sealed class SimpleProjectPackage : Package { ... public const string SimpleProjectPkgString = "96bf4c26-d94e-43bf-a56a-f8500b52bfad"; public const string SimpleProjectFactoryString = "471EC4BB-E47E-4229-A789-D1F5F83B52D4"; public static readonly Guid guidSimpleProjectFactory = new Guid(SimpleProjectFactoryString); }
Adicione uma classe à pasta SimpleProject superior chamada SimpleProjectFactory.cs.
Adicione o seguinte usando as orientações:
using System.Runtime.InteropServices; using Microsoft.VisualStudio.Shell;
Adicione um atributo GUID à
SimpleProjectFactory
classe. O valor do atributo é o novo GUID de fábrica do projeto.[Guid(SimpleProjectPackage.SimpleProjectFactoryString)] class SimpleProjectFactory { }
Agora você pode registrar seu modelo de projeto.
Para registrar o modelo de projeto
Em SimpleProjectPackage.cs, adicione um ProvideProjectFactoryAttribute atributo à
SimpleProjectPackage
classe, da seguinte maneira.[ProvideProjectFactory( typeof(SimpleProjectFactory), "Simple Project", "Simple Project Files (*.myproj);*.myproj", "myproj", "myproj", @"Templates\Projects\SimpleProject", LanguageVsTemplate = "SimpleProject")] [Guid(SimpleProjectPackage.PackageGuidString)] public sealed class SimpleProjectPackage : Package
Recrie a solução e verifique se ela é compilada sem erros.
A reconstrução registra o modelo de projeto.
Os parâmetros
defaultProjectExtension
epossibleProjectExtensions
são definidos para a extensão de nome de arquivo do projeto (.myproj). OprojectTemplatesDirectory
parâmetro é definido como o caminho relativo da pasta Modelos . Durante a compilação, esse caminho será convertido em uma compilação completa e adicionado ao registro para registrar o sistema do projeto.
Testar o registro do modelo
O registro de modelo informa ao Visual Studio o local da pasta de modelo de projeto para que o Visual Studio possa exibir o nome e o ícone do modelo na caixa de diálogo Novo Projeto .
Para testar o registro do modelo
Pressione F5 para iniciar a depuração de uma instância experimental do Visual Studio.
Na instância experimental, crie um novo projeto do seu tipo de projeto recém-criado. Na caixa de diálogo Novo Projeto, você deve ver SimpleProject em Modelos instalados.
Agora você tem uma fábrica de projetos que está registrada. No entanto, ele ainda não pode criar um projeto. O pacote de projeto e a fábrica de projetos trabalham juntos para criar e inicializar um projeto.
Adicionar o código do Managed Package Framework
Implemente a conexão entre o pacote do projeto e a fábrica do projeto.
Importe os arquivos de código-fonte para o Managed Package Framework.
Descarregue o projeto SimpleProject (no Gerenciador de Soluções, selecione o nó do projeto e, no menu de contexto, clique em Descarregar Projeto.) e abra o arquivo de projeto no editor XML.
Adicione os seguintes blocos ao arquivo de projeto (logo acima dos <blocos Importar> ). Defina
ProjectBasePath
como o local do arquivo ProjectBase.files no código do Managed Package Framework que você acabou de baixar. Talvez seja necessário adicionar uma barra invertida ao nome do caminho. Se você não fizer isso, o projeto pode não conseguir localizar o código-fonte do Managed Package Framework.<PropertyGroup> <ProjectBasePath>your path here\</ProjectBasePath> <RegisterWithCodebase>true</RegisterWithCodebase> </PropertyGroup> <Import Project="$(ProjectBasePath)\ProjectBase.Files" />
Importante
Não se esqueça da barra invertida no final do caminho.
Recarregue o projeto .
Adicione referências aos assemblies a seguir:
Microsoft.VisualStudio.Designer.Interfaces
(em <Instalação> do VSSDK\VisualStudioIntegration\Common\Assemblies\v2.0)WindowsBase
Microsoft.Build.Tasks.v4.0
Para inicializar a fábrica do projeto
No arquivo SimpleProjectPackage.cs adicione a seguinte
using
diretiva.using Microsoft.VisualStudio.Project;
Derive a
SimpleProjectPackage
classe deMicrosoft.VisualStudio.Package.ProjectPackage
.public sealed class SimpleProjectPackage : ProjectPackage
Registre a fábrica do projeto. Adicione a seguinte linha ao
SimpleProjectPackage.Initialize
método, logo apósbase.Initialize
.base.Initialize(); this.RegisterProjectFactory(new SimpleProjectFactory(this));
Implemente a propriedade
ProductUserContext
abstrata :public override string ProductUserContext { get { return ""; } }
Em SimpleProjectFactory.cs, adicione a seguinte
using
diretiva após as diretivas existentesusing
.using Microsoft.VisualStudio.Project;
Derive a
SimpleProjectFactory
classe deProjectFactory
.class SimpleProjectFactory : ProjectFactory
Adicione o seguinte método fictício à
SimpleProjectFactory
classe. Você implementará esse método em uma seção posterior.protected override ProjectNode CreateProject() { return null; }
Adicione o seguinte campo e construtor à
SimpleProjectFactory
classe. EssaSimpleProjectPackage
referência é armazenada em cache em um campo privado para que possa ser usada na configuração de um site de provedor de serviços.private SimpleProjectPackage package; public SimpleProjectFactory(SimpleProjectPackage package) : base(package) { this.package = package; }
Recrie a solução e verifique se ela é compilada sem erros.
Testar a implementação da fábrica do projeto
Teste se o construtor para a implementação da fábrica do projeto é chamado.
Para testar a implementação da fábrica do projeto
No arquivo SimpleProjectFactory.cs defina um ponto de interrupção na seguinte linha no
SimpleProjectFactory
construtor.this.package = package;
Pressione F5 para iniciar uma instância experimental do Visual Studio.
Na instância experimental, comece a criar um novo projeto. Na caixa de diálogo Novo Projeto, selecione o tipo de projeto SimpleProject e clique em OK. A execução é interrompida no ponto de interrupção.
Limpe o ponto de interrupção e pare a depuração. Como ainda não criamos um nó de projeto, o código de criação do projeto ainda lança exceções.
Estender a classe ProjectNode
Agora você pode implementar a SimpleProjectNode
classe, que deriva da ProjectNode
classe. A ProjectNode
classe base lida com as seguintes tarefas de criação de projeto:
Copia o arquivo de modelo de projeto, SimpleProject.myproj, para a nova pasta de projeto. A cópia é renomeada de acordo com o nome inserido na caixa de diálogo Novo Projeto . O
ProjectGuid
valor da propriedade é substituído por um novo GUID.Percorre os elementos MSBuild do arquivo de modelo de projeto, SimpleProject.myproj, e procura
Compile
elementos. Para cadaCompile
arquivo de destino, copia o arquivo para a nova pasta do projeto.A classe derivada
SimpleProjectNode
lida com estas tarefas:Permite que ícones para nós de projeto e arquivo no Gerenciador de Soluções sejam criados ou selecionados.
Permite que substituições de parâmetros de modelo de projeto adicionais sejam especificadas.
Para estender a classe ProjectNode
Adicione uma classe chamada
SimpleProjectNode.cs
.Substitua o código existente pelo código a seguir.
using System; using System.Collections.Generic; using Microsoft.VisualStudio.Project; namespace SimpleProject { public class SimpleProjectNode : ProjectNode { private SimpleProjectPackage package; public SimpleProjectNode(SimpleProjectPackage package) { this.package = package; } public override Guid ProjectGuid { get { return SimpleProjectPackage.guidSimpleProjectFactory; } } public override string ProjectType { get { return "SimpleProjectType"; } } public override void AddFileFromTemplate( string source, string target) { this.FileTemplateProcessor.UntokenFile(source, target); this.FileTemplateProcessor.Reset(); } } }
Essa
SimpleProjectNode
implementação de classe tem estes métodos substituídos:
ProjectGuid
, que retorna o GUID de fábrica do projeto.ProjectType
, que retorna o nome localizado do tipo de projeto.AddFileFromTemplate
, que copia os arquivos selecionados da pasta de modelo para o projeto de destino. Esse método é implementado em uma seção posterior.O
SimpleProjectNode
construtor, como oSimpleProjectFactory
construtor, armazena em cache uma referência emSimpleProjectPackage
um campo privado para uso posterior.Para conectar a
SimpleProjectFactory
classe àSimpleProjectNode
classe, você deve instanciar um novoSimpleProjectNode
noSimpleProjectFactory.CreateProject
método e armazená-lo em cache em um campo privado para uso posterior.
Para conectar a classe de fábrica do projeto e a classe de nó
No arquivo SimpleProjectFactory.cs adicione a seguinte
using
diretiva:using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
Substitua o método usando o
SimpleProjectFactory.CreateProject
código a seguir.protected override ProjectNode CreateProject() { SimpleProjectNode project = new SimpleProjectNode(this.package); project.SetSite((IOleServiceProvider) ((IServiceProvider)this.package).GetService( typeof(IOleServiceProvider))); return project; }
Recrie a solução e verifique se ela é compilada sem erros.
Testar a classe ProjectNode
Teste sua fábrica de projetos para ver se ela cria uma hierarquia de projeto.
Para testar a classe ProjectNode
Pressione F5 para iniciar a depuração. Na instância experimental, crie um novo SimpleProject.
O Visual Studio deve chamar sua fábrica de projetos para criar um projeto.
Feche a Instância Experimental do Visual Studio.
Adicionar um ícone de nó de projeto personalizado
O ícone do nó do projeto na seção anterior é um ícone padrão. Você pode alterá-lo para um ícone personalizado.
Para adicionar um ícone de nó de projeto personalizado
Na pasta Recursos, adicione um arquivo de bitmap chamado SimpleProjectNode.bmp.
Nas janelas Propriedades, reduza o bitmap para 16 por 16 pixels. Torne o bitmap distinto.
Na janela Propriedades, altere a ação Criar do bitmap para Recurso Incorporado.
Em SimpleProjectNode.cs, adicione as seguintes
using
diretivas:using System.Drawing; using System.Windows.Forms;
Adicione o seguinte campo estático e construtor à
SimpleProjectNode
classe.private static ImageList imageList; static SimpleProjectNode() { imageList = Utilities.GetImageList( typeof(SimpleProjectNode).Assembly.GetManifestResourceStream( "SimpleProject.Resources.SimpleProjectNode.bmp")); }
Adicione a seguinte propriedade ao início da
SimpleProjectNode
classe.internal static int imageIndex; public override int ImageIndex { get { return imageIndex; } }
Substitua o construtor de instância com o código a seguir.
public SimpleProjectNode(SimpleProjectPackage package) { this.package = package; imageIndex = this.ImageHandler.ImageList.Images.Count; foreach (Image img in imageList.Images) { this.ImageHandler.AddImage(img); } }
Durante a construção estática,
SimpleProjectNode
recupera o bitmap do nó do projeto dos recursos de manifesto do assembly e o armazena em cache em um campo particular para uso posterior. Observe a sintaxe do caminho da GetManifestResourceStream imagem. Para ver os nomes dos recursos de manifesto incorporados em um assembly, use o GetManifestResourceNames método. Quando esse método é aplicado aoSimpleProject
assembly, os resultados devem ser os seguintes:
SimpleProject.Resources.resources
VisualStudio.Project.resources
SimpleProject.VSPackage.resources
Recursos.imagelis.bmp
Microsoft.VisualStudio.Project.DontShowAgainDialog.resources
Microsoft.VisualStudio.Project.SecurityWarningDialog.resources
SimpleProject.Resources.SimpleProjectNode.bmp
Durante a construção da instância, a
ProjectNode
classe base carrega Resources.imagelis.bmp, na qual são incorporados bitmaps 16 x 16 de Resources\imagelis.bmp. Essa lista de bitmaps é disponibilizada paraSimpleProjectNode
comoImageHandler.ImageList
.SimpleProjectNode
Acrescenta o bitmap do nó do projeto à lista. O deslocamento do bitmap do nó do projeto na lista de imagens é armazenado em cache para uso posterior como o valor da propriedade públicaImageIndex
. Visual Studio usa essa propriedade para determinar qual bitmap exibir como o ícone do nó do projeto.
Testar o ícone do nó do projeto personalizado
Teste a fábrica do projeto para ver se ela cria uma hierarquia de projeto que tenha o ícone do nó do projeto personalizado.
Para testar o ícone do nó do projeto personalizado
Inicie a depuração e, na instância experimental, crie um novo SimpleProject.
No projeto recém-criado, observe que SimpleProjectNode.bmp é usado como o ícone do nó do projeto.
Abra Program.cs no editor de códigos. Você deve ver o código-fonte semelhante ao código a seguir.
using System; using System.Collections.Generic; using System.Text; namespace $nameSpace$ { public class $className$ { static void Main(string[] args) { Console.WriteLine("Hello VSX!!!"); Console.ReadKey(); } } }
Observe que os parâmetros do modelo $nameSpace$ e $className$ não possuem novos valores. Você aprenderá a implementar a substituição de parâmetros de modelo na próxima seção.
Substituir parâmetros de modelo
Em uma seção anterior, você registrou o modelo de projeto com o Visual Studio usando o ProvideProjectFactory
atributo . Registrar o caminho de uma pasta de modelo dessa maneira permite habilitar a substituição de parâmetros básicos de modelo substituindo e expandindo a ProjectNode.AddFileFromTemplate
classe. Para obter mais informações, consulte Nova geração de projeto: sob o capô, parte dois.
Agora adicione o código de substituição à AddFileFromTemplate
classe.
Para substituir parâmetros de modelo
No arquivo SimpleProjectNode.cs , adicione a diretiva a seguir
using
.using System.IO;
Substitua o método usando o
AddFileFromTemplate
código a seguir.public override void AddFileFromTemplate( string source, string target) { string nameSpace = this.FileTemplateProcessor.GetFileNamespace(target, this); string className = Path.GetFileNameWithoutExtension(target); this.FileTemplateProcessor.AddReplace("$nameSpace$", nameSpace); this.FileTemplateProcessor.AddReplace("$className$", className); this.FileTemplateProcessor.UntokenFile(source, target); this.FileTemplateProcessor.Reset(); }
Defina um ponto de interrupção no método, logo após a
className
instrução de atribuição.As instruções de atribuição determinam valores razoáveis para um namespace e um novo nome de classe. As duas
ProjectNode.FileTemplateProcessor.AddReplace
chamadas de método substituem os valores de parâmetro de modelo correspondentes usando esses novos valores.
Testar a substituição do parâmetro do modelo
Agora você pode testar a substituição de parâmetros de modelo.
Para testar a substituição do parâmetro de modelo
Inicie a depuração e, na instância experimental, crie um novo SimpleProject.
A execução pára no ponto de interrupção no
AddFileFromTemplate
método.Examine os valores para os
nameSpace
parâmetros eclassName
.nameSpace
é fornecido o valor do elemento RootNamespace no arquivo de modelo de <projeto \Templates\Projects\SimpleProject\SimpleProject.myproj.> Nesse caso, o valor éMyRootNamespace
.className
é dado o valor do nome do arquivo de origem da classe, sem a extensão de nome de arquivo. Nesse caso, o primeiro arquivo a ser copiado para a pasta de destino é AssemblyInfo.cs; portanto, o valor de className é .AssemblyInfo
Remova o ponto de interrupção e pressione F5 para continuar a execução.
Visual Studio deve concluir a criação de um projeto.
Abra Program.cs no editor de códigos. Você deve ver o código-fonte semelhante ao código a seguir.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyRootNamespace { public class Program { static void Main(string[] args) { Console.WriteLine("Hello VSX!!!"); Console.ReadKey(); } } }
Observe que o namespace é agora e o nome da classe é agora
MyRootNamespace
Program
.Comece a depuração do projeto. O novo projeto deve compilar, executar e exibir "Hello VSX!!" na janela do console.
Parabéns! Você implementou um sistema básico de projeto gerenciado.