Как стать автором
Поиск
Написать публикацию
Обновить

Visual Studio 2005/2008 PasteBin via C#

Проект описанный в данной статье являет собой мой первый опыт программирования на C# .NET, посему — прошу не судить строго.

Многие из нас пользуются Microsoft Visual Studio и, я полагаю, большинство для обмена кодом использует клевый ресурс http://pastebin.com

«Так зачем тратить время на загрузку этого сайта в браузере, копипаст кода в форму и нажатие кнопок», — подумал я и решил написать плагин для Студии, добавляющий в контекстное меню редактора кода пункт «PasteBin». Простым кликом на него вы заставите выделенную часть исходного кода переслаться на http://pastebin.com и, после этого, уникальный URL, созданный сайтом PasteBin окажется в вашем буфер обмена.

Для работы я использую Microsoft Visual Studio 2008, но в 2005 — все абсолютно аналогично.

Итак, все начинается с создания проекта.


Далее будут заданы несколько вопросов и, в итоге, перед вами появится заготовка будущего плагина. Исходный код любого плагина должен содержать некоторые стандартные функции. Сейчас я последовательно расскажу что за что отвечает и в каком порядке вызывается.

Для начала объявим глобальные переменные нашего стандартного класса Connect.

        // Constants for command properties<br>        private const string CommandName        = "PasteBin";<br>        private const string CommandCaption     = "PasteBin";<br>        private const string Url                = "http://pastebin.com";<br>        private const string RequestParameters  = "parent_pid=&format={0}&code2={1}&poster=&paste=Send&expiry=f&email=";<br><br>        // Constants for file formats<br>        private static readonly Dictionary<string, string> FileFormat = new Dictionary<string, string><br>                                                                            {<br>                                                                             {"c","c"},<br>                                                                             {"h","c"},<br>                                                                             {"cpp","cpp"},<br>                                                                             {"cs","csharp"}<br>                                                                            };<br><br>        // Variables for IDE and add-in instances<br>        private DTE _applicationObject;<br>        private AddIn _addInInstance;<br><br>        // Buttons that will be created on built-in command bars of Visual Studio<br>        // We must keep them at class level to remove them when the add-in is unloaded<br>        private CommandBarButton _pasteBinButton;<br><br>* This source code was highlighted with Source Code Highlighter.

Первая стандартная функция OnConnection описывает на каком этапе загрузки Студии необходимо внедрять наши изменения в пользовательский интерфейс. Для статьи она интереса не представляет, желающие смогут увидеть ее в полном исходном коде, который будет приложен в конце статьи. Гораздо больший интерес представляет функция AddUI, описывающая непосредственно процесс добавления нового пункта в контекстное меню (кстати, AddUI вызывается также и второй стандартной функцией — OnStartupComplete, что гарантирует корректную загрузку нашего плагина, даже если при старте Студии возникли проблемы).

Итак, функция AddUI. Вначале мы проверяем не создана ли уже команда с таким именем как у нас (мало ли) и если нет, то создаем ее сами.

                // Try to retrieve the command, just in case it was already created, ignoring the <br>                // exception that would happen if the command was not created yet.<br>                try<br>                {<br>                    myCommand = _applicationObject.Commands.Item(_addInInstance.ProgID + "." + CommandName, -1);<br>                }<br>                catch (Exception e)<br>                {<br>                    Debug.Write(e.ToString());<br>                }<br><br>                // Add the command if it does not exist<br>                if (myCommand == null)<br>                {<br>                    myCommand = _applicationObject.Commands.AddNamedCommand(_addInInstance,<br>                      CommandName, CommandCaption, null, true, 59, ref contextUIGuids,<br>                      (int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));<br>                }<br><br>* This source code was highlighted with Source Code Highlighter.

Далее получаем «указатель» на контекстное меню редактора кода.

                // Constants for names of built-in command bars of Visual Studio<br>                const string vsCodeWindowCommandbarName = "Code Window";<br><br>                // Retrieve the collection of command bars<br>                // Note:<br>                // - In VS.NET 2002/2003 (which uses the Office.dll reference) <br>                //  DTE.CommandBars returns directly a CommandBars type, so a cast <br>                //  to CommandBars is redundant<br>                // - In VS 2005 or higher (which uses the new Microsoft.VisualStudio.CommandBars.dll reference) <br>                //  DTE.CommandBars returns an Object type, so we do need a cast to CommandBars<br>                var commandBars = (CommandBars)_applicationObject.CommandBars;<br><br>                // Retrieve some built-in command bars<br>                codeCommandBar = commandBars[vsCodeWindowCommandbarName];<br><br>* This source code was highlighted with Source Code Highlighter.

И описываем наш пункт в контекстном меню, не забывая про его внешний вид — иконку.

                // Create the buttons from the commands<br>                // Note:<br>                // - In VS.NET 2002/2003 (which uses the Office.dll reference) <br>                //  Command.AddControl returns directly a CommandBarControl type, so a cast <br>                //  to CommandBarControl is redundant<br>                // - In VS 2005 or higher (which uses the new Microsoft.VisualStudio.CommandBars.dll reference) <br>                //  Command.AddControl returns an Object type, so we do need a cast to CommandBarControl<br><br>                string ns = GetType().Namespace;<br>                Assembly currentAssembly = GetType().Assembly;<br><br>                Stream<br>                    imgStreamPic = currentAssembly.GetManifestResourceStream(ns + "." + "klipper.png"),<br>                    imgStreamMask = currentAssembly.GetManifestResourceStream(ns + "." + "klipper-mask.png");<br><br>                if (imgStreamPic != null && imgStreamMask != null)<br>                {<br>                    Image<br>                        pasteBinImage = Image.FromStream(imgStreamPic),<br>                        pasteBinImageMask = Image.FromStream(imgStreamMask);<br><br>                    // ------------------------------------------------------------------------------------<br>                    // Button on the "Code Window" context menu<br>                    // ------------------------------------------------------------------------------------<br><br>                    // Add a button to the built-in "Code Window" context menu<br>                    _pasteBinButton = (CommandBarButton) myCommand.AddControl(codeCommandBar,<br>                                                                             codeCommandBar.Controls.Count + 1);<br><br>                    // Change some button properties<br>                    _pasteBinButton.Caption = CommandCaption;<br>                    _pasteBinButton.BeginGroup = true; // Separator line above button<br><br>                    _pasteBinButton.Style = MsoButtonStyle.msoButtonIconAndCaption; // It could be also msoButtonIcon<br>                    _pasteBinButton.Picture = (stdole.StdPicture) ImageConverter.ImageToIpicture(pasteBinImage);<br>                    _pasteBinButton.Mask = (stdole.StdPicture) ImageConverter.ImageToIpicture(pasteBinImageMask);<br>                }<br><br>* This source code was highlighted with Source Code Highlighter.

Для получения ресурсов с помощью GetManifestResourceStream необходимо добавить нужные файлы в проект и изменить в свойствах параметр Build Action на Embeded Resource.



Далее следуют три абсолютно неинтересных функции OnDisconnection, OnBeginShutdown и OnAddInsUpdate. Зато сразу же после них располагается сердце нашего проекта — функция Exec.

Если какой-либо фрагмент кода выделен, то тогда на основе типа активного файла с исходным кодом и преобразованного с помощью UrlEncode выделенного текста формируется запрос к сайту
http://pastebin.com, а из ответа сервера вычленяется уникальная ссылка на размещенный исходный код, которая и помещается в буфер обмена.

        public void Exec(string cmdName, vsCommandExecOption executeOption, ref object varIn,<br>          ref object varOut, ref bool handled)<br>        {<br><br>            handled = false;<br><br>            if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)<br>            {<br>                if (cmdName == string.Format("{0}.{1}", _addInInstance.ProgID, CommandName))<br>                {<br>                    handled = true;<br>                    if (!((TextSelection)_applicationObject.ActiveDocument.Selection).IsEmpty)<br>                    {<br>                        // parameters: name1=value1&name2=value2    <br>                        var webRequest = (HttpWebRequest)WebRequest.Create(Url);<br><br>                        webRequest.ContentType = "application/x-www-form-urlencoded";<br>                        webRequest.Method = "POST";<br><br>                        // formatting request string from document type and selection<br>                        string request = string.Format(RequestParameters,<br>                            FileFormat[_applicationObject.ActiveDocument.Name.Split('.')[1]],<br>                            System.Web.HttpUtility.UrlEncode(((TextSelection)_applicationObject.ActiveDocument.Selection).Text));<br><br>                        Stream os = null;<br><br>                        try<br>                        { // send the POST<br>                            webRequest.ContentLength = request.Length; //Length of request to send<br>                            os = webRequest.GetRequestStream();<br>                            os.Write(System.Text.Encoding.GetEncoding("windows-1251").GetBytes(request), 0, request.Length);    //Send it<br>                        }<br>                        catch (WebException ex)<br>                        {<br>                            MessageBox.Show(ex.Message, "HttpPost: Request error",<br>                              MessageBoxButtons.OK, MessageBoxIcon.Error);<br>                        }<br>                        finally<br>                        {<br>                            if (os != null)<br>                            {<br>                                os.Close();<br>                            }<br>                        }<br><br>                        try<br>                        { // get the response<br>                            var webResponse = (HttpWebResponse)webRequest.GetResponse();<br>                            if (webResponse != null)<br>                            { // copy to clipboard<br>                                Clipboard.SetText(webResponse.ResponseUri.ToString());<br>                                MessageBox.Show("Upload successfully. Url is copied in your clipboard.");<br>                            }<br>                        }<br>                        catch (WebException ex)<br>                        {<br>                            MessageBox.Show(ex.Message, "HttpPost: Response error",<br>                              MessageBoxButtons.OK, MessageBoxIcon.Error);<br>                        }<br>                    }<br>                }<br>            }<br>        }<br><br>* This source code was highlighted with Source Code Highlighter.

Завершает файл также ничем не примечательная стандартная функция QueryStatus.

Приложение А.
1.
Содержание основного файла Connect.cs
2. Содержание вспомогательного файла ImageConverter.cs
На сайт http://pastebin.com вышеуказанные исходники добавлены при помощи описанного в статье плагина.

Приложение Б.
Файлы к статье
Файлы PasteBin.AddIn и PasteBin.dll необходимо поместить в каталог %USERPROFILE%\Мои Документы\Visual Studio 2008\Addins. 2008 можно заменить на 2005.
_________
Текст подготовлен в ХабраРедакторе
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.