Создание базовой системы проекта, часть 1
В Visual Studio проекты — это контейнеры, используемые разработчиками для упорядочивания файлов исходного кода и других ресурсов. Проекты отображаются как дочерние элементы решений в Обозреватель решений. Проекты позволяют упорядочивать, создавать, отлаживать и развертывать исходный код и создавать ссылки на веб-службы, базы данных и другие ресурсы.
Проекты определяются в файлах проекта, например CSPROJ-файл для проекта Visual C#. Вы можете создать собственный тип проекта с собственным расширением имени файла проекта. Дополнительные сведения о типах проектов см. в разделе "Типы проектов".
Примечание.
Если вам нужно расширить Visual Studio с пользовательским типом проекта, настоятельно рекомендуется использовать систему проектов Visual Studio (VSPS), которая имеет ряд преимуществ при создании системы проектов с нуля:
Проще подключиться. Даже для базовой системы проектов требуется десятки тысяч строк кода. Использование VSPS сокращает затраты на подключение до нескольких щелчков, прежде чем вы будете готовы настроить его в соответствии с вашими потребностями.
Упрощенное обслуживание. Используя VSPS, необходимо поддерживать только собственные сценарии. Мы обрабатываем обновление всей инфраструктуры системы проекта.
Если вам нужно использовать версии Visual Studio старше Visual Studio 2013, вы не сможете использовать VSPS в расширении Visual Studio. Если это так, это пошаговое руководство является хорошим местом для начала работы.
В этом пошаговом руководстве показано, как создать тип проекта с расширением имени файла проекта .myproj. Это пошаговое руководство по заимствованию из существующей системы проектов Visual C#.
Примечание.
Дополнительные примеры проектов расширений см . в примерах VSSDK.
В этом пошаговом руководстве показано, как выполнить следующие задачи:
Создайте базовый тип проекта.
Создайте базовый шаблон проекта.
Зарегистрируйте шаблон проекта в Visual Studio.
Создайте экземпляр проекта, открыв диалоговое окно "Новый проект" , а затем с помощью шаблона.
Создайте фабрику проектов для системы проекта.
Создайте узел проекта для системы проекта.
Добавьте настраиваемые значки для системы проекта.
Реализуйте базовую подстановку параметров шаблона.
Необходимые компоненты
Скачайте исходный код для управляемой платформы пакетов для проектов. Извлеките файл в расположение, доступное для создаваемого решения.
Создание базового типа проекта
Создайте проект VSIX C# с именем SimpleProject. (Файл>нового>проекта и visual C#>Extensibility>VSIX Project). Добавьте шаблон элемента проекта пакета Visual Studio (в Обозреватель решений щелкните правой кнопкой мыши узел проекта и выберите пункт "Добавить>новый элемент", а затем перейдите к пакету Visual Studio расширяемости>). Присвойте файлу SimpleProjectPackage.
Создание базового шаблона проекта
Теперь вы можете изменить этот базовый VSPackage, чтобы реализовать новый тип проекта myproj . Чтобы создать проект, основанный на типе проекта myproj , Visual Studio должен знать, какие файлы, ресурсы и ссылки необходимо добавить в новый проект. Чтобы предоставить эти сведения, поместите файлы проекта в папку шаблона проекта. Когда пользователь использует проект myproj для создания проекта, файлы копируются в новый проект.
Создание базового шаблона проекта
Добавьте три папки в проект, один из них: Templates\Projects\SimpleProject. (в Обозреватель решений щелкните правой кнопкой мыши узел проекта SimpleProject, наведите указатель на "Добавить" и нажмите кнопку "Создать папку". Назовите шаблоны папок. В папке "Шаблоны" добавьте папку с именем Projects. В папке "Проекты" добавьте папку с именем SimpleProject.)
В папке Templates\Projects\SimpleProject добавьте файл изображения растрового изображения для использования в качестве значка с именем SimpleProject.ico. При нажатии кнопки "Добавить" откроется редактор значков.
Сделайте значок отличительным. Этот значок появится в диалоговом окне "Новый проект " далее в пошаговом руководстве.
Сохраните значок и закройте редактор значков.
В папке Templates\Projects\SimpleProject добавьте элемент класса с именем Program.cs.
Замените существующий код следующими строками.
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(); } } }
Важно!
Это не окончательная форма кода Program.cs . Параметры замены будут рассмотрены на следующем шаге. Возможно, вы увидите ошибки компиляции, но если файл BuildAction — Content, вы сможете создать и запустить проект как обычно.
Сохраните файл.
Скопируйте файл AssemblyInfo.cs из папки свойств в папку Projects\SimpleProject.
В папке Projects\SimpleProject добавьте XML-файл с именем SimpleProject.myproj.
Примечание.
Расширение имени файла для всех проектов этого типа — myproj. Если вы хотите изменить его, его необходимо изменить везде, где оно упоминание в пошаговом руководстве.
Замените существующее содержимое следующими строками.
<?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>
Сохраните файл.
В окне свойств задайте для действия сборки AssemblyInfo.cs, Program.cs, SimpleProject.ico и SimpleProject.myproject.myproj значение Content и задайте для свойства VSIX значение True.
Этот шаблон проекта описывает базовый проект Visual C# с конфигурацией отладки и конфигурацией выпуска. Проект включает два исходных файла, AssemblyInfo.cs и Program.cs и несколько ссылок на сборки. При создании проекта из шаблона значение ProjectGuid автоматически заменяется новым GUID.
В Обозреватель решений папка развернутых шаблонов должна отображаться следующим образом:
Templates
Projects
SimpleProject
AssemblyInfo.cs
Program.cs
SimpleProject.ico
SimpleProject.myproj
Создание базовой фабрики проектов
Необходимо указать Visual Studio расположение папки шаблона проекта. Для этого добавьте атрибут в класс VSPackage, реализующий фабрику проектов, чтобы расположение шаблона записывается в системный реестр при построении VSPackage. Начните с создания базовой фабрики проектов, определяемой GUID фабрики проектов. ProvideProjectFactoryAttribute Используйте атрибут для подключения фабрики проектов к классуSimpleProjectPackage
.
Создание базовой фабрики проектов
Создайте идентификаторы GUID для фабрики проектов (в меню "Сервис " щелкните "Создать GUID") или используйте его в следующем примере. Добавьте идентификаторы
SimpleProjectPackage
GUID в класс рядом с разделом с уже определеннымPackageGuidString
. Идентификаторы GUID должны находиться как в форме GUID, так и в строковой форме. Полученный код должен выглядеть следующим образом.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); }
Добавьте класс в верхнюю папку SimpleProject с именем SimpleProjectFactory.cs.
Добавьте следующие директивы using:
using System.Runtime.InteropServices; using Microsoft.VisualStudio.Shell;
Добавьте атрибут GUID в
SimpleProjectFactory
класс. Значение атрибута — это новый GUID фабрики проектов.[Guid(SimpleProjectPackage.SimpleProjectFactoryString)] class SimpleProjectFactory { }
Теперь вы можете зарегистрировать шаблон проекта.
Регистрация шаблона проекта
В SimpleProjectPackage.cs добавьте ProvideProjectFactoryAttribute атрибут в
SimpleProjectPackage
класс, как показано ниже.[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
Перестройте решение и убедитесь, что она выполняет сборку без ошибок.
Перестроение регистрирует шаблон проекта.
Параметры
defaultProjectExtension
иpossibleProjectExtensions
задаются расширением имени файла проекта (MYPROJ). ПараметрprojectTemplatesDirectory
имеет относительный путь к папке "Шаблоны ". Во время сборки этот путь будет преобразован в полную сборку и добавлен в реестр для регистрации системы проекта.
Проверка регистрации шаблона
Регистрация шаблона сообщает Visual Studio расположение папки шаблона проекта, чтобы Visual Studio отображала имя шаблона и значок в диалоговом окне "Новый проект ".
Проверка регистрации шаблона
Нажмите клавишу F5 , чтобы начать отладку экспериментального экземпляра Visual Studio.
В экспериментальном экземпляре создайте новый проект нового типа проекта. В диалоговом окне "Новый проект" вы увидите SimpleProject в разделе "Установленные шаблоны".
Теперь у вас есть фабрика проектов, зарегистрированная. Однако он еще не может создать проект. Пакет проекта и фабрика проектов работают вместе для создания и инициализации проекта.
Добавление кода управляемой платформы пакетов
Реализуйте подключение между пакетом проекта и фабрикой проектов.
Импортируйте файлы исходного кода для управляемой платформы пакетов.
Выгрузите проект SimpleProject (в Обозреватель решений выберите узел проекта и в контекстном меню щелкните "Выгрузить проект".) и откройте файл проекта в редакторе XML.
Добавьте следующие блоки в файл проекта (чуть выше блоков импорта<>). Задайте
ProjectBasePath
расположение файла ProjectBase.files в коде управляемой платформы пакетов, который вы только что скачали. Возможно, потребуется добавить обратную косую черту в имя пути. Если это не так, проект может не найти исходный код Управляемой платформы пакетов.<PropertyGroup> <ProjectBasePath>your path here\</ProjectBasePath> <RegisterWithCodebase>true</RegisterWithCodebase> </PropertyGroup> <Import Project="$(ProjectBasePath)\ProjectBase.Files" />
Важно!
Не забывайте обратную косую черту в конце пути.
Перезагрузите проект .
Добавьте ссылки на следующие сборки:
Microsoft.VisualStudio.Designer.Interfaces
(в <VSSDK install>\VisualStudioIntegration\Common\Assemblies\v2.0)WindowsBase
Microsoft.Build.Tasks.v4.0
Инициализация фабрики проектов
В файле SimpleProjectPackage.cs добавьте следующую
using
директиву.using Microsoft.VisualStudio.Project;
Производный
SimpleProjectPackage
класс отMicrosoft.VisualStudio.Package.ProjectPackage
.public sealed class SimpleProjectPackage : ProjectPackage
Зарегистрируйте фабрику проектов. Добавьте следующую строку в
SimpleProjectPackage.Initialize
метод сразу послеbase.Initialize
.base.Initialize(); this.RegisterProjectFactory(new SimpleProjectFactory(this));
Реализуйте абстрактное свойство
ProductUserContext
:public override string ProductUserContext { get { return ""; } }
В SimpleProjectFactory.cs добавьте следующую
using
директиву после существующихusing
директив.using Microsoft.VisualStudio.Project;
Производный
SimpleProjectFactory
класс отProjectFactory
.class SimpleProjectFactory : ProjectFactory
Добавьте следующий фиктивный метод в
SimpleProjectFactory
класс. Этот метод будет реализован в следующем разделе.protected override ProjectNode CreateProject() { return null; }
Добавьте в класс следующее
SimpleProjectFactory
поле и конструктор. ЭтаSimpleProjectPackage
ссылка кэшируется в закрытом поле, чтобы его можно было использовать при настройке сайта поставщика услуг.private SimpleProjectPackage package; public SimpleProjectFactory(SimpleProjectPackage package) : base(package) { this.package = package; }
Перестройте решение и убедитесь, что она выполняет сборку без ошибок.
Тестирование реализации фабрики проектов
Проверьте, вызывается ли конструктор для реализации фабрики проектов.
Тестирование реализации фабрики проектов
В файле SimpleProjectFactory.cs задайте точку останова в следующей строке конструктора
SimpleProjectFactory
.this.package = package;
Нажмите клавишу F5 , чтобы запустить экспериментальный экземпляр Visual Studio.
В экспериментальном экземпляре начните создавать новый проект. В диалоговом окне "Создать проект" выберите тип проекта SimpleProject и нажмите кнопку "ОК". Выполнение прекратится в точке останова.
Снимите точку останова и остановите отладку. Так как мы еще не создали узел проекта, код создания проекта по-прежнему создает исключения.
Расширение класса ProjectNode
Теперь можно реализовать класс, производный SimpleProjectNode
от ProjectNode
класса. Базовый ProjectNode
класс обрабатывает следующие задачи создания проекта:
Копирует файл шаблона проекта SimpleProject.myproj в новую папку проекта. Копия переименовывается в соответствии с именем, введенным в диалоговом окне "Новый проект ".
ProjectGuid
Значение свойства заменяется новым ИДЕНТИФИКАТОРом GUID.Проходит по элементам MSBuild файла шаблона проекта SimpleProject.myprojj и ищет
Compile
элементы. Для каждогоCompile
целевого файла копирует файл в новую папку проекта.Производный
SimpleProjectNode
класс обрабатывает следующие задачи:Позволяет создавать или выбирать значки для узлов проекта и файлов в Обозреватель решений.
Позволяет указывать дополнительные подстановки параметров шаблона проекта.
Расширение класса ProjectNode
Добавьте класс с именем
SimpleProjectNode.cs
.Замените существующий код следующим кодом:
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(); } } }
Эта
SimpleProjectNode
реализация класса имеет следующие переопределенные методы:
ProjectGuid
, который возвращает GUID фабрики проектов.ProjectType
— возвращает локализованное имя типа проекта.AddFileFromTemplate
, который копирует выбранные файлы из папки шаблона в целевой проект. Этот метод будет реализован далее в следующем разделе.Конструктор
SimpleProjectNode
, напримерSimpleProjectFactory
конструктор, кэширует ссылкуSimpleProjectPackage
в частном поле для последующего использования.Чтобы подключить
SimpleProjectFactory
класс кSimpleProjectNode
классу, необходимо создать экземпляр новогоSimpleProjectNode
методаSimpleProjectFactory.CreateProject
и кэшировать его в частном поле для последующего использования.
Подключение класса фабрики проекта и класса узла
В файле SimpleProjectFactory.cs добавьте следующую
using
директиву:using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
Замените
SimpleProjectFactory.CreateProject
метод следующим кодом.protected override ProjectNode CreateProject() { SimpleProjectNode project = new SimpleProjectNode(this.package); project.SetSite((IOleServiceProvider) ((IServiceProvider)this.package).GetService( typeof(IOleServiceProvider))); return project; }
Перестройте решение и убедитесь, что она выполняет сборку без ошибок.
Тестирование класса ProjectNode
Проверьте фабрику проектов, чтобы узнать, создает ли она иерархию проектов.
Тестирование класса ProjectNode
Нажмите клавишу F5, чтобы запустить отладку. В экспериментальном экземпляре создайте новый SimpleProject.
Visual Studio должен вызвать фабрику проектов для создания проекта.
Закройте экспериментальный экземпляр Visual Studio.
Добавление значка пользовательского узла проекта
Значок узла проекта в предыдущем разделе — это значок по умолчанию. Его можно изменить на пользовательский значок.
Добавление значка пользовательского узла проекта
В папке Resources добавьте файл растрового изображения с именем SimpleProjectNode.bmp.
В окнах свойств уменьшите растровое изображение до 16 на 16 пикселей. Сделайте растровое изображение отличительным.
В окне "Свойства" измените действие сборки растрового изображения на внедренный ресурс.
В SimpleProjectNode.cs добавьте следующие
using
директивы:using System.Drawing; using System.Windows.Forms;
Добавьте в класс следующее
SimpleProjectNode
статическое поле и конструктор.private static ImageList imageList; static SimpleProjectNode() { imageList = Utilities.GetImageList( typeof(SimpleProjectNode).Assembly.GetManifestResourceStream( "SimpleProject.Resources.SimpleProjectNode.bmp")); }
Добавьте следующее свойство в начало
SimpleProjectNode
класса.internal static int imageIndex; public override int ImageIndex { get { return imageIndex; } }
Замените конструктор экземпляра следующим кодом.
public SimpleProjectNode(SimpleProjectPackage package) { this.package = package; imageIndex = this.ImageHandler.ImageList.Images.Count; foreach (Image img in imageList.Images) { this.ImageHandler.AddImage(img); } }
Во время статического построения
SimpleProjectNode
извлекает растровое изображение узла проекта из ресурсов манифеста сборки и кэширует его в частном поле для последующего использования. Обратите внимание на синтаксис GetManifestResourceStream пути изображения. Чтобы просмотреть имена ресурсов манифеста, внедренных в сборку, используйте GetManifestResourceNames этот метод. Если этот метод применяется к сборкеSimpleProject
, результаты должны быть следующими:
SimpleProject.Resources.resources
VisualStudio.Project.resources
SimpleProject.VSPackage.resources
Resources.imagelis.bmp
Microsoft.VisualStudio.Project.DontShowAgainDialog.resources
Microsoft.VisualStudio.Project.SecurityWarningDialog.resources
SimpleProject.Resources.SimpleProjectNode.bmp
Во время построения экземпляра базовый класс загружает Resources.imagelis.bmp, в котором обычно используются 16 х 16 растровых изображений из Resources\imagelis.bmp.
ProjectNode
Этот список растровых карт доступен какSimpleProjectNode
ImageHandler.ImageList
.SimpleProjectNode
добавляет растровое изображение узла проекта в список. Смещение растрового изображения узла проекта в списке изображений кэшируется для последующего использования в качестве значения общедоступногоImageIndex
свойства. Visual Studio использует это свойство для определения растрового изображения, отображаемого в виде значка узла проекта.
Проверка значка пользовательского узла проекта
Проверьте фабрику проектов, чтобы узнать, создает ли она иерархию проектов с значком пользовательского узла проекта.
Проверка значка пользовательского узла проекта
Начните отладку и в экспериментальном экземпляре создайте новый SimpleProject.
В созданном проекте обратите внимание, что SimpleProjectNode.bmp используется в качестве значка узла проекта.
Откройте файл Program.cs в редакторе кода. Вы увидите исходный код, похожий на следующий код.
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(); } } }
Обратите внимание, что параметры шаблона $nameSpace$ и $className$ не имеют новых значений. Вы узнаете, как реализовать подстановку параметров шаблона в следующем разделе.
Замена параметров шаблона
В предыдущем разделе вы зарегистрировали шаблон проекта в Visual Studio с помощью атрибута ProvideProjectFactory
. Регистрация пути к папке шаблона таким образом позволяет включить базовую подстановку параметров шаблона, переопределив и расширив ProjectNode.AddFileFromTemplate
класс. Дополнительные сведения см. в статье "Новое поколение проектов: под капотом" часть 2.
Теперь добавьте код замены в AddFileFromTemplate
класс.
Замена параметров шаблона
В файле SimpleProjectNode.cs добавьте следующую
using
директиву.using System.IO;
Замените
AddFileFromTemplate
метод следующим кодом.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(); }
Установите точку останова в методе сразу после инструкции
className
назначения.Инструкции присваивания определяют разумные значения для пространства имен и нового имени класса. Вызовы двух
ProjectNode.FileTemplateProcessor.AddReplace
методов заменяют соответствующие значения параметров шаблона с помощью этих новых значений.
Проверка подстановки параметров шаблона
Теперь можно проверить подстановку параметров шаблона.
Проверка подстановки параметров шаблона
Начните отладку и в экспериментальном экземпляре создайте новый SimpleProject.
Выполнение останавливается в точке останова в методе
AddFileFromTemplate
.Проверьте значения для
nameSpace
параметров иclassName
параметров.nameSpace
получает значение <элемента RootNamespace> в файле шаблона проекта \Templates\Projects\SimpleProject\SimpleProject.myproject.myproj . В этом случае используется значениеMyRootNamespace
.className
присваивается значение имени исходного файла класса без расширения имени файла. В этом случае первый файл, копируемый в целевую папку, — AssemblyInfo.cs, поэтому значение className равноAssemblyInfo
.
Удалите точку останова и нажмите клавишу F5 , чтобы продолжить выполнение.
Visual Studio должен завершить создание проекта.
Откройте файл Program.cs в редакторе кода. Вы увидите исходный код, похожий на следующий код.
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(); } } }
Обратите внимание, что пространство имен теперь и
MyRootNamespace
имя класса теперьProgram
.Начните отладку проекта. Новый проект должен компилировать, запускать и отображать "Hello VSX!!" в окне консоли.
Поздравляем! Вы реализовали базовую управляемую систему проектов.