Страницы

Поиск по вопросам

Показаны сообщения с ярлыком visual-studio-extensions. Показать все сообщения
Показаны сообщения с ярлыком visual-studio-extensions. Показать все сообщения

среда, 22 января 2020 г.

Копирование файла настроек в шаблоне проекта Visual Studio

#c_sharp #visual_studio_2017 #visual_studio_extensions


Делаю шаблон проекта VS и хочу, чтобы создаваемый проект содержал настройки и аргументы
запуска внешней программы. Файл с настройками должен быть просто скопирован в каталог
проекта. 

Сами настройки VS хранит в файле $projectname$.csproj.user на который нет никаких
ссылок из файла проекта (.csproj).

Тут возникает проблема: VS не копирует файлы, которые не задействованы в файле проекта.
В $projectname$.csproj должно быть прописано что-то вроде такого , чтобы файл $projectname$.csproj.user был, все-таки, скопирован. Но тогда он появляется
в Solution Explorer и настройки из него считываются только после переоткрытия решения.

Project.vstemplate:


    
      AssemblyInfo.cs
      ProjectTemplate.csproj.user
    



Как можно решить эту проблему?
    


Ответы

Ответ 1



Можно скрыть элемент в Solution Explorer, если указать значение метасвойства Visible: За старый формат проекта не отвечаю. Скорее всего, там надо указывать отдельным элементом: false Это поможет избавиться от лишнего элемента в проекте, но вряд ли поможет с чтением настроек только после переоткрытия решения. Это попахивает ограничением IDE: разработчики, скорее всего, просто не рассчитывали, что пользовательские настройки будут создаваться не пользователем. Кстати, если перейдёте на новый формат проекта, то там профили запуска лежат отдельным красивым файлом launchSettings.json, и профилей может быть много с разными настройками. Рекомендую.

воскресенье, 22 декабря 2019 г.

Создание расширений VS, сортировка using по длине строки

#visual_studio_2017 #visual_studio_extensions


Товарищи, проблема следующая: привык в своих проектах сортировать usingи (и не только)
по длине строки. То есть код рода:

using System.Collections.Generic;
using System;
using System.Linq;
using System.IO;


Я обязательно переделаю в:

using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;


И только тогда успокоюсь) 
Так вот. Я немного устал делать это вручную, так что хочу спросить: есть ли какое-либо
легкое расширение (подозреваю, что ReSharper так умеет, но его я не рассматриваю) для
Visual Studio 2017, способное выполнять сортировку выделенных строк по их длине?
    


Ответы

Ответ 1



Собственно, никто мне так и не ответил, сам же я не нашел подходящего расширения. Но кто ж мне мешал написать свое? Сие я и сделал. Расширение теперь висит в Marketplace, а именно - здесь. Оформлять сильно все это я, понятное дело, не стал, ибо делал сие только под себя, но мало ли кому-то когда-нибудь тоже пригодится такая мелочь, а ставить внушительные расширения хотят далеко не все. Ну и давайте заодно уж рассмотрим пример создания такого простейшего расширения на поставленной задаче. 0) Для начала создадим VSIX Project (расширения для Visual Studio можно писать на Visual C++, Visual Basic, C#. Я это дело писал на C#). Если шаблон такого проекта отсутствует в списке доступных, установите соответствующий пункт с помощью Visual Studio Installer. 1) Добавим в проект элемент Custom Command и назовем его "CommandSort". В появившийся класс "CommandSort.cs" добавим следующий код: using System; using System.Linq; using Microsoft.VisualStudio.Shell; using System.ComponentModel.Design; namespace LineSorter { internal sealed class CommandSort { #region Var private AsyncPackage Package { get; } public int CommandId { get; } = 0x0100; public static CommandSort Instance { get; private set; } public static Guid CommandSet { get; } = new Guid("e9f69e2b-6313-4c2b-9765-1ddd6439d519"); #endregion #region Init private CommandSort(AsyncPackage Package, OleMenuCommandService CommandService) { this.Package = Package ?? throw new ArgumentNullException(nameof(Package)); CommandService = CommandService ?? throw new ArgumentNullException(nameof(CommandService)); CommandID menuCommandID = new CommandID(CommandSet, CommandId); MenuCommand menuItem = new MenuCommand(Execute, menuCommandID); CommandService.AddCommand(menuItem); } public static async System.Threading.Tasks.Task InitializeAsync(AsyncPackage Package) { ThreadHelper.ThrowIfNotOnUIThread(); Instance = new CommandSort(Package, await Package.GetServiceAsync((typeof(IMenuCommandService))) as OleMenuCommandService); } #endregion #region Functions private void Execute(object sender, EventArgs e) { ThreadHelper.ThrowIfNotOnUIThread(); TextSelection.GetSelection(Package).OrderBy(x => x.Length).ThenBy(x => x).ReplaceSelection(); } #endregion } } Инициализатор нашей команды, ее ID и GUID в рамках проекта будут установлены VS автоматически. По сути от нас требуется изменить лишь метод Execute. 2) Для более удобной работы с выделенным текстом создадим класс "TextSelection" и в "TextSelection.cs" внесем таковой код: using EnvDTE; using System; using System.Linq; using System.Windows; using System.Collections.Generic; using Microsoft.VisualStudio.TextManager.Interop; namespace LineSorter { public static class TextSelection { #region Var public static IServiceProvider ServiceProvider { get; set; } #endregion #region Functions /// /// Получим выделенный текст и избавим его от пробелов и табуляции в начале/конце строк /// public static IEnumerable GetSelection(IServiceProvider ServiceProvider) { TextSelection.ServiceProvider = ServiceProvider; IVsTextManager2 textManager = ServiceProvider.GetService(typeof(SVsTextManager)) as IVsTextManager2; int result = textManager.GetActiveView2(1, null, (uint)_VIEWFRAMETYPE.vftCodeWindow, out IVsTextView view); view.GetSelectedText(out string selectedText); return selectedText.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim(new char[] { ' ', '\t' })); } public static void ReplaceSelection(this IEnumerable Selections) { ReplaceSelection(Selections, ServiceProvider); } /// /// Заменим выделенный текст на указанную коллекцию строк /// public static void ReplaceSelection(this IEnumerable Selections, IServiceProvider ServiceProvider) { DTE dte = ServiceProvider?.GetService(typeof(DTE)) as DTE; if (dte is null) return; IDataObject obj = Clipboard.GetDataObject(); Clipboard.SetText(string.Join("\r\n", Selections)); dte.ExecuteCommand("Edit.Paste"); Clipboard.SetDataObject(obj); } #endregion } } Логика кода, думаю, вполне ясна. Однако заострю внимание на методе замены выделенного текста на новую коллекцию (ReplaceSelection). Изначально код выглядел так: DTE dte = ServiceProvider?.GetService(typeof(DTE)) as DTE; if (dte is null) return; EnvDTE.TextSelection selection = dte.ActiveDocument?.Selection as EnvDTE.TextSelection; if (selection is null) return; selection.Text = string.Join("\r\n", Selections); И все кажется вполне логичным: просто заменяем выделенный текст на новый. Во многих мануалах я как раз такой подход и видел. Однако предостерегаю от такого подхода к работе с выделенным текстом, так как работает это жутко медленно. Свойство EnvDTE.TextSelection.Text при установке зачем-то парсит весь вставляемый текст, разбивая его на смысловые единицы. Поясню: к примеру, мы имеем 2 таких using'a, которые мы хотим отсортировать: using Microsoft.VisualStudio.Shell.Interop; using Task = System.Threading.Tasks.Task; Для нашего алгоритма важно лишь то, что это 2 строки. Однако указанное свойство разбивает все это дело на смысловой набор: using, Microsoft, VisualStudio, Shell, Interop, using, Task, System, Threading, Tasks, Task И мы имеем уже не 2 строки, а 11 отдельно обрабатываемых элементов. С ростом числа сортируемых строк число обрабатываемых смысловых единиц катастрофически растет, так что простенькое действие при таком подходе начинает занимать внушительный промежуток времени. Именно поэтому я воспользовался маленькой хитростью: Я сохраняю текущее состояние буфера обмена После этого загоняю в него объединенную коллекцию наших строк А теперь уже запускаю функцию вставки из самой VS (как бы Ctrl + V). Так что текст моментально вставляется на место выделенного, после чего форматируется самой средой После сего действа возвращаю буферу обмена прошлое состояние Честно - не знаю, насколько хорошо это решение, однако оно уж точно быстрее стандартного пути. Если будут идеи более правильной реализации - буду рад выслушать! 3) Что ж. Разобрались, собственно, с кодом. Осталось навести порядок в конфиге (CommandSortPackage.vsct): Таким образом мы добавляем кнопку с указанным текстом и ссылающуюся на наше действие в контекстное меню VS, а также связываем с ним горячие клавиши: (Ctrl + E) + (Ctrl + L) 4) Вот и все, наше простенькое расширение готово. Вы можете отдебажить его с помощью экспериментальной версии VS, или же просто собрать его, после чего среди уймы пакетов Вы найдете заветный файлик с расширением *.vsix, при помощи которого Вы можете либо сразу установить расширение в свою студию, либо же даже опубликовать его) А на сием - все) Спасибо за внимание)

воскресенье, 15 декабря 2019 г.

Расширение для Visual Studio 2013: добавление кнопки в стандартное (контекстное) меню

#visual_studio #visual_studio_2013 #visual_studio_extensions


Как добавить дополнительную кнопку в стандартное контекстное меню, которое появляется
при щелчке правой кнопкой мыши рядом с кодом?

Например такая функциональность: 


правый щелчок вызывает стандартное меню
в меню помимо стандартных есть новая кнопка
щелчок по ней вызывает действие (например появляется сообщение)

    


Ответы

Ответ 1



Ответ частично найден. Надо просто создать стандартный проект - Visual Stutio Package. Выбрать Menu Command в качестве интерфейса в диалоговом окне при создании (первый вариант). Потом открыть файл .vsct и поменять родителя у группы: Именно Привяжет группу (с кнопкой) в меню, появляющееся при нажатии правой кнопкой в коде. тут важен id этого меню IDM_VS_CTXT_CODEWIN и стандартный guid guidSHLMainMenu. Можно посмотреть другие id и guid (лучше в VS - там с описанием) https://msdn.microsoft.com/ru-ru/library/vstudio/microsoft.visualstudio.shell.vsmenus_members(v=vs.100).aspx#mainBody В обработчике можно написать что угодно и оно заработает private void MenuItemCallback(object sender, EventArgs e) { MessageBox.Show("Уже что-то заработало!!!"); }

Как положить свой ProjectTemplate в раздел VisualSudio (Visual C#/Web)?

#c_sharp #visual_studio #visual_studio_2015 #visual_studio_extensions


Привет! Я пытаюсь затолкать свой шаблон проекта в (Visual C#/Web)(Аналогично тому
как там лежит DevExpress Template Gallery на моём скриншоте). Пытаюсь сделать это следующими
строками кода в файле MyTemplate.vstemplate:


My Template Gallery
Start Template Gallery
myProj.ico
CSharp
Web
Web
4.0
0
0
4d72892d-abc3-428d-8fa7-8421a83d6e0a
true
XafariApplication
true




    


Ответы

Ответ 1



Ручной способ Создаете проект. Заполняете нужными начальными файлами для шаблона. Сохраняете. В меню Файл выбираете Экспорт шаблона. В Wizard'е выбираете: Project Template. Заполняете поля. Архив закинется в папку <Рабочая папка студии>\My Exported Templates и в папку <Рабочая папка студии>\Templates\ProjectTemplates (если не сняли галку в wizard'е): Этот архив нужно поместить в папку <Рабочая папка студии>\Templates\ProjectTemplates\Visual C#\Web (ее нет, поэтому необходимо создать): Заходите в студию. И Profit. С помощью VSIX Дожен быть готов архив. Смотри 1-5 пункты ручного способа. Создаете проект VSIX. В проекте создаете нужную иерархию папок. В данном случае получается следующая иерархия: Закидывайте архив в папку ProjectTemplates\CSharp\Web. В манифесте указываете нужные данные. Затем заходите в пункт Assets и добавляете: Сохраняетесь. Билдитесь. Запускаете VSIX. Открываете студию. ProjectTemplate + VSIX Создаете проект типа ProjectTemplate заполняете его. Выбираете в студии файл с расширением *.vstemplate (по умолчанию его имя совпадает с именем проекта). И в его свойствах в строке Category прописываете путь иерархии, который будет начинаться от CSharp. Т.е. если указываете SubA/SubB/SubC, то шаблон будет лежать в CSharp/SubA/SubB/SubC. В нашем случае указываем только Web: Создаем проект VSIX. В манифесте указываете нужные данные: Билдитесь. P.S. Немного про элемент TemplateData. Вы указали ProjectSubType значение Web, но этот элемент может иметь только всего 4 значения: SmartDevice-NETCFv1 - указывает поддержку .NET Compact Framework версии 1.0 SmartDevice-NETCFv1 - указывает поддержку .NET Compact Framework версии 2.0 CSharp - Задается только тогда, когда элемент ProjectType имеет значение Web (т.е. это проект типа веб-сайт). Указывает на языка программирования. VisualBasic - тоже самое, что и предыдущий пункт, только язык программирования VisualBasic.

понедельник, 15 июля 2019 г.

Добавление папок и файлов в конечный zip архив шаблона проекта VS 2015 во время сборки

Здравствуйте друзья!
После создания проекта Visual Studio (Visual C#\Extensibility\C# Project Template), удаления тега вместе с его содержимым в файле MyTemplate.vstemplate мы получаем вот такой проект:

После сборки этого проекта в папке **bin** образуется архив с двумя файлами:

Как настроить проект таким образом, что-бы при сборке в этот архив ложилась ещё произвольная папка с произвольными файлами из проекта?

При этом нельзя что-бы шаблон генерировал все эти файлы при запуске его ярлыка из VisualStudio(т.е. нельзя добавлять файлы в файл с расширением .vstemplate как я понимаю)
(А делать этого нельзя т.к. этот шаблон используется для вызова WizardTemplate который уже сам генерирует шаблон по пути который передан от самого Template. А собственно файлы которые находятся в шаблоне по условию нужно использовать в этом Wizard'e. Такие дела)
Заранее спасибо за помощь!


Ответ

Смог решить данную проблему с помощью Post Build Action. Файлы прикрепил к проекту с действием при компилляции "None", а в PostBuildAction написал скрипт доупаковку архива zip с помощью утилиты 7z.

Собственный конструктор пользовательских компонентов

Всем привет!
Можно ли как-нибудь самостоятельно написать свой конструктор пользовательских компонентов? Я заметил что в некоторых фреймворках для Visual Studio существуют собственные конструкторы пользовательских компонентов (DevExpress к примеру).
Где можно прочесть о создании собственных конструкторов? Заранее спасибо!


Ответ

Нашел книгу в которой есть сведенья о дизайнере компонентов, сервисах и о разработке компонентов в целом, которые могут пригодиться в разработке.
1) C#. Разработка компонентов в MS Visual Studio 2005/2008 (Павел Агуров)
Так-же полезную информацию удалось найти в архиве MSDN:
2) Writing Custom Designers for .NET Components
3) Разработка собственного дизайнера форм для .NET-приложений
Если кто-то находил или найдёт ещё информацию по дизайнерам, то буду очень благодарен если вы дополните ответ!

воскресенье, 7 июля 2019 г.

Создание расширений VS, сортировка using по длине строки

Товарищи, проблема следующая: привык в своих проектах сортировать usingи (и не только) по длине строки. То есть код рода:
using System.Collections.Generic; using System; using System.Linq; using System.IO;
Я обязательно переделаю в:
using System; using System.IO; using System.Linq; using System.Collections.Generic;
И только тогда успокоюсь) Так вот. Я немного устал делать это вручную, так что хочу спросить: есть ли какое-либо легкое расширение (подозреваю, что ReSharper так умеет, но его я не рассматриваю) для Visual Studio 2017, способное выполнять сортировку выделенных строк по их длине?


Ответ

Собственно, никто мне так и не ответил, сам же я не нашел подходящего расширения. Но кто ж мне мешал написать свое? Сие я и сделал. Расширение теперь висит в Marketplace, а именно - здесь Оформлять сильно все это я, понятное дело, не стал, ибо делал сие только под себя, но мало ли кому-то когда-нибудь тоже пригодится такая мелочь, а ставить внушительные расширения хотят далеко не все. Ну и давайте заодно уж рассмотрим пример создания такого простейшего расширения на поставленной задаче.

0) Для начала создадим VSIX Project (расширения для Visual Studio можно писать на Visual C++, Visual Basic, C#. Я это дело писал на C#). Если шаблон такого проекта отсутствует в списке доступных, установите соответствующий пункт с помощью Visual Studio Installer.
1) Добавим в проект элемент Custom Command и назовем его "CommandSort". В появившийся класс "CommandSort.cs" добавим следующий код:
using System; using System.Linq; using Microsoft.VisualStudio.Shell; using System.ComponentModel.Design;
namespace LineSorter { internal sealed class CommandSort { #region Var private AsyncPackage Package { get; } public int CommandId { get; } = 0x0100; public static CommandSort Instance { get; private set; } public static Guid CommandSet { get; } = new Guid("e9f69e2b-6313-4c2b-9765-1ddd6439d519"); #endregion
#region Init private CommandSort(AsyncPackage Package, OleMenuCommandService CommandService) { this.Package = Package ?? throw new ArgumentNullException(nameof(Package)); CommandService = CommandService ?? throw new ArgumentNullException(nameof(CommandService)); CommandID menuCommandID = new CommandID(CommandSet, CommandId); MenuCommand menuItem = new MenuCommand(Execute, menuCommandID); CommandService.AddCommand(menuItem); } public static async System.Threading.Tasks.Task InitializeAsync(AsyncPackage Package) { ThreadHelper.ThrowIfNotOnUIThread(); Instance = new CommandSort(Package, await Package.GetServiceAsync((typeof(IMenuCommandService))) as OleMenuCommandService); } #endregion
#region Functions private void Execute(object sender, EventArgs e) { ThreadHelper.ThrowIfNotOnUIThread(); TextSelection.GetSelection(Package).OrderBy(x => x.Length).ThenBy(x => x).ReplaceSelection(); } #endregion } }
Инициализатор нашей команды, ее ID и GUID в рамках проекта будут установлены VS автоматически. По сути от нас требуется изменить лишь метод Execute 2) Для более удобной работы с выделенным текстом создадим класс "TextSelection" и в "TextSelection.cs" внесем таковой код:
using EnvDTE; using System; using System.Linq; using System.Windows; using System.Collections.Generic; using Microsoft.VisualStudio.TextManager.Interop;
namespace LineSorter { public static class TextSelection { #region Var public static IServiceProvider ServiceProvider { get; set; } #endregion
#region Functions ///

/// Получим выделенный текст и избавим его от пробелов и табуляции в начале/конце строк /// public static IEnumerable GetSelection(IServiceProvider ServiceProvider) { TextSelection.ServiceProvider = ServiceProvider; IVsTextManager2 textManager = ServiceProvider.GetService(typeof(SVsTextManager)) as IVsTextManager2; int result = textManager.GetActiveView2(1, null, (uint)_VIEWFRAMETYPE.vftCodeWindow, out IVsTextView view); view.GetSelectedText(out string selectedText); return selectedText.Split(new char[] { '
', '
' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim(new char[] { ' ', '\t' })); }
public static void ReplaceSelection(this IEnumerable Selections) { ReplaceSelection(Selections, ServiceProvider); } /// /// Заменим выделенный текст на указанную коллекцию строк /// public static void ReplaceSelection(this IEnumerable Selections, IServiceProvider ServiceProvider) { DTE dte = ServiceProvider?.GetService(typeof(DTE)) as DTE; if (dte is null) return; IDataObject obj = Clipboard.GetDataObject(); Clipboard.SetText(string.Join("
", Selections)); dte.ExecuteCommand("Edit.Paste"); Clipboard.SetDataObject(obj); } #endregion } }
Логика кода, думаю, вполне ясна. Однако заострю внимание на методе замены выделенного текста на новую коллекцию (ReplaceSelection). Изначально код выглядел так:
DTE dte = ServiceProvider?.GetService(typeof(DTE)) as DTE; if (dte is null) return; EnvDTE.TextSelection selection = dte.ActiveDocument?.Selection as EnvDTE.TextSelection; if (selection is null) return; selection.Text = string.Join("
", Selections);
И все кажется вполне логичным: просто заменяем выделенный текст на новый. Во многих мануалах я как раз такой подход и видел. Однако предостерегаю от такого подхода к работе с выделенным текстом, так как работает это жутко медленно. Свойство EnvDTE.TextSelection.Text при установке зачем-то парсит весь вставляемый текст, разбивая его на смысловые единицы. Поясню: к примеру, мы имеем 2 таких using'a, которые мы хотим отсортировать:
using Microsoft.VisualStudio.Shell.Interop; using Task = System.Threading.Tasks.Task;
Для нашего алгоритма важно лишь то, что это 2 строки. Однако указанное свойство разбивает все это дело на смысловой набор:
using, Microsoft, VisualStudio, Shell, Interop, using, Task, System, Threading, Tasks, Task
И мы имеем уже не 2 строки, а 11 отдельно обрабатываемых элементов. С ростом числа сортируемых строк число обрабатываемых смысловых единиц катастрофически растет, так что простенькое действие при таком подходе начинает занимать внушительный промежуток времени. Именно поэтому я воспользовался маленькой хитростью:
Я сохраняю текущее состояние буфера обмена После этого загоняю в него объединенную коллекцию наших строк А теперь уже запускаю функцию вставки из самой VS (как бы Ctrl + V). Так что текст моментально вставляется на место выделенного, после чего форматируется самой средой После сего действа возвращаю буферу обмена прошлое состояние
Честно - не знаю, насколько хорошо это решение, однако оно уж точно быстрее стандартного пути. Если будут идеи более правильной реализации - буду рад выслушать!
3) Что ж. Разобрались, собственно, с кодом. Осталось навести порядок в конфиге (CommandSortPackage.vsct):






Таким образом мы добавляем кнопку с указанным текстом и ссылающуюся на наше действие в контекстное меню VS, а также связываем с ним горячие клавиши: (Ctrl + E) + (Ctrl + L) 4) Вот и все, наше простенькое расширение готово. Вы можете отдебажить его с помощью экспериментальной версии VS, или же просто собрать его, после чего среди уймы пакетов Вы найдете заветный файлик с расширением *.vsix, при помощи которого Вы можете либо сразу установить расширение в свою студию, либо же даже опубликовать его)

А на сием - все) Спасибо за внимание)

воскресенье, 10 марта 2019 г.

Копирование файла настроек в шаблоне проекта Visual Studio

Делаю шаблон проекта VS и хочу, чтобы создаваемый проект содержал настройки и аргументы запуска внешней программы. Файл с настройками должен быть просто скопирован в каталог проекта.
Сами настройки VS хранит в файле $projectname$.csproj.user на который нет никаких ссылок из файла проекта (.csproj).
Тут возникает проблема: VS не копирует файлы, которые не задействованы в файле проекта. В $projectname$.csproj должно быть прописано что-то вроде такого , чтобы файл $projectname$.csproj.user был, все-таки, скопирован. Но тогда он появляется в Solution Explorer и настройки из него считываются только после переоткрытия решения.
Project.vstemplate:
AssemblyInfo.cs ProjectTemplate.csproj.user
Как можно решить эту проблему?


Ответ


Можно скрыть элемент в Solution Explorer, если указать значение метасвойства Visible

За старый формат проекта не отвечаю. Скорее всего, там надо указывать отдельным элементом:
false
Это поможет избавиться от лишнего элемента в проекте, но вряд ли поможет с чтением настроек только после переоткрытия решения. Это попахивает ограничением IDE: разработчики, скорее всего, просто не рассчитывали, что пользовательские настройки будут создаваться не пользователем.
Кстати, если перейдёте на новый формат проекта, то там профили запуска лежат отдельным красивым файлом launchSettings.json, и профилей может быть много с разными настройками. Рекомендую.

пятница, 26 октября 2018 г.

Расширение для Visual Studio 2013: добавление кнопки в стандартное (контекстное) меню

Как добавить дополнительную кнопку в стандартное контекстное меню, которое появляется при щелчке правой кнопкой мыши рядом с кодом?
Например такая функциональность:
правый щелчок вызывает стандартное меню в меню помимо стандартных есть новая кнопка щелчок по ней вызывает действие (например появляется сообщение)


Ответ

Ответ частично найден.
Надо просто создать стандартный проект - Visual Stutio Package. Выбрать Menu Command в качестве интерфейса в диалоговом окне при создании (первый вариант). Потом открыть файл .vsct и поменять родителя у группы:

Именно

Привяжет группу (с кнопкой) в меню, появляющееся при нажатии правой кнопкой в коде. тут важен id этого меню IDM_VS_CTXT_CODEWIN и стандартный guid guidSHLMainMenu. Можно посмотреть другие id и guid (лучше в VS - там с описанием) https://msdn.microsoft.com/ru-ru/library/vstudio/microsoft.visualstudio.shell.vsmenus_members(v=vs.100).aspx#mainBody
В обработчике можно написать что угодно и оно заработает
private void MenuItemCallback(object sender, EventArgs e) { MessageBox.Show("Уже что-то заработало!!!"); }

Как положить свой ProjectTemplate в раздел VisualSudio (Visual C#/Web)?

Привет! Я пытаюсь затолкать свой шаблон проекта в (Visual C#/Web)(Аналогично тому как там лежит DevExpress Template Gallery на моём скриншоте). Пытаюсь сделать это следующими строками кода в файле MyTemplate.vstemplate:
My Template Gallery Start Template Gallery myProj.ico CSharp Web Web 4.0 0 0 4d72892d-abc3-428d-8fa7-8421a83d6e0a true XafariApplication true


Ответ

Ручной способ
Создаете проект. Заполняете нужными начальными файлами для шаблона. Сохраняете.
В меню Файл выбираете Экспорт шаблона. В Wizard'е выбираете: Project Template. Заполняете поля. Архив закинется в папку <Рабочая папка студии>\My Exported Templates и в папку <Рабочая папка студии>\Templates\ProjectTemplates (если не сняли галку в wizard'е): Этот архив нужно поместить в папку <Рабочая папка студии>\Templates\ProjectTemplates\Visual C#\Web (ее нет, поэтому необходимо создать): Заходите в студию. И Profit.
С помощью VSIX
Дожен быть готов архив. Смотри 1-5 пункты ручного способа Создаете проект VSIX. В проекте создаете нужную иерархию папок. В данном случае получается следующая иерархия: Закидывайте архив в папку ProjectTemplates\CSharp\Web В манифесте указываете нужные данные. Затем заходите в пункт Assets и добавляете: Сохраняетесь. Билдитесь. Запускаете VSIX. Открываете студию.
ProjectTemplate + VSIX
Создаете проект типа ProjectTemplate заполняете его. Выбираете в студии файл с расширением *.vstemplate (по умолчанию его имя совпадает с именем проекта). И в его свойствах в строке Category прописываете путь иерархии, который будет начинаться от CSharp. Т.е. если указываете SubA/SubB/SubC, то шаблон будет лежать в CSharp/SubA/SubB/SubC. В нашем случае указываем только Web: Создаем проект VSIX. В манифесте указываете нужные данные: Билдитесь.
P.S. Немного про элемент TemplateData. Вы указали ProjectSubType значение Web, но этот элемент может иметь только всего 4 значения:
SmartDevice-NETCFv1 - указывает поддержку .NET Compact Framework версии 1.0 SmartDevice-NETCFv1 - указывает поддержку .NET Compact Framework версии 2.0 CSharp - Задается только тогда, когда элемент ProjectType имеет значение Web (т.е. это проект типа веб-сайт). Указывает на языка программирования. VisualBasic - тоже самое, что и предыдущий пункт, только язык программирования VisualBasic