📜 ⬆️ ⬇️

Visual Studio 2005/2008 PasteBin via C #

The project described in this article is my first programming experience in C # .NET, therefore I ask you not to judge strictly.

Many of us use Microsoft Visual Studio and, I believe, most of them use a cool resource for code sharing.

“So why waste time downloading this site in a browser, copying code into a form and pressing buttons,” I thought, and decided to write a plugin for Studio that adds the “PasteBin” item to the context menu of the code editor. With a simple click on it, you will force the selected part of the source code to be sent to and, after this, the unique URL created by the PasteBin site will be in your clipboard.
')
I use Microsoft Visual Studio 2008 for work, but in 2005 everything is absolutely the same.


Creating a project

Next will be asked a few questions and, as a result, you will see the preparation of the future plug-in. The source code of any plugin must contain some standard functions. Now I will consistently tell what is responsible for what and in what order it is called.

To begin, let's declare the global variables of our standard Connect class.

// Constants for command properties
private const string CommandName = "PasteBin" ;
private const string CommandCaption = "PasteBin" ;
private const string Url = "http://pastebin.com" ;
private const string RequestParameters = "parent_pid=&format={0}&code2={1}&poster=&paste=Send&expiry=f&email=" ;

// Constants for file formats
private static readonly Dictionary< string , string > FileFormat = new Dictionary< string , string >
{
{ "c" , "c" },
{ "h" , "c" },
{ "cpp" , "cpp" },
{ "cs" , "csharp" }
};

// Variables for IDE and add-in instances
private DTE _applicationObject;
private AddIn _addInInstance;

// Buttons that will be created on built-in command bars of Visual Studio
// We must keep them at class level to remove them when the add-in is unloaded
private CommandBarButton _pasteBinButton;


* This source code was highlighted with Source Code Highlighter .


The first standard OnConnection function describes at what stage of the Studio download it is necessary to implement our changes in the user interface. For the article, it is of no interest, anyone will be able to see it in the full source code, which will be attached at the end of the article. Much more interesting is the AddUI function, which describes directly the process of adding a new item to the context menu (by the way, AddUI is also caused by the second standard function - OnStartupComplete , which guarantees the correct loading of our plug-in, even if there were problems at the start of the Studio).

So, the AddUI function. First, we check if a team with the same name as ours has already been created (whether it is not enough) and if not, then create it ourselves.

// Try to retrieve the command, just in case it was already created, ignoring the
// exception that would happen if the command was not created yet.
try
{
myCommand = _applicationObject.Commands.Item(_addInInstance.ProgID + "." + CommandName, -1);
}
catch (Exception e)
{
Debug.Write(e.ToString());
}

// Add the command if it does not exist
if (myCommand == null )
{
myCommand = _applicationObject.Commands.AddNamedCommand(_addInInstance,
CommandName, CommandCaption, null , true , 59, ref contextUIGuids,
( int )(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));
}


* This source code was highlighted with Source Code Highlighter .


Next we get a “pointer” to the context menu of the code editor.

// Constants for names of built-in command bars of Visual Studio
const string vsCodeWindowCommandbarName = "Code Window" ;

// Retrieve the collection of command bars
// Note:
// - In VS.NET 2002/2003 (which uses the Office.dll reference)
// DTE.CommandBars returns directly a CommandBars type, so a cast
// to CommandBars is redundant
// - In VS 2005 or higher (which uses the new Microsoft.VisualStudio.CommandBars.dll reference)
// DTE.CommandBars returns an Object type, so we do need a cast to CommandBars
var commandBars = (CommandBars)_applicationObject.CommandBars;
// Retrieve some built-in command bars
codeCommandBar = commandBars[vsCodeWindowCommandbarName];


* This source code was highlighted with Source Code Highlighter .


And we describe our item in the context menu, without forgetting about its appearance - the icon.

// Create the buttons from the commands
// Note:
// - In VS.NET 2002/2003 (which uses the Office.dll reference)
// Command.AddControl returns directly a CommandBarControl type, so a cast
// to CommandBarControl is redundant
// - In VS 2005 or higher (which uses the new Microsoft.VisualStudio.CommandBars.dll reference)
// Command.AddControl returns an Object type, so we do need a cast to CommandBarControl
string ns = GetType().Namespace;
Assembly currentAssembly = GetType(). Assembly ;

Stream
imgStreamPic = currentAssembly.GetManifestResourceStream(ns + "." + "klipper.png" ),
imgStreamMask = currentAssembly.GetManifestResourceStream(ns + "." + "klipper-mask.png" );

if (imgStreamPic != null && imgStreamMask != null )
{
Image
pasteBinImage = Image.FromStream(imgStreamPic),
pasteBinImageMask = Image.FromStream(imgStreamMask);

// ------------------------------------------------------------------------------------
// Button on the "Code Window" context menu
// ------------------------------------------------------------------------------------

// Add a button to the built-in "Code Window" context menu
_pasteBinButton = (CommandBarButton) myCommand.AddControl(codeCommandBar,
codeCommandBar.Controls.Count + 1);

// Change some button properties
_pasteBinButton.Caption = CommandCaption;
_pasteBinButton.BeginGroup = true ; // Separator line above button

_pasteBinButton.Style = MsoButtonStyle.msoButtonIconAndCaption; // It could be also msoButtonIcon
_pasteBinButton.Picture = (stdole.StdPicture) ImageConverter.ImageToIpicture(pasteBinImage);
_pasteBinButton.Mask = (stdole.StdPicture) ImageConverter.ImageToIpicture(pasteBinImageMask);
}


* This source code was highlighted with Source Code Highlighter .


To get resources using GetManifestResourceStream, you need to add the necessary files to the project and change the Build Action parameter in the properties to Embeded Resource .



The following are three absolutely uninteresting functions OnDisconnection , OnBeginShutdown and OnAddInsUpdate . But immediately after them is the heart of our project - the Exec function.

If any code fragment is selected, then based on the type of the active file with the source code and the selected text converted using UrlEncode , a request to the site is formed, and a unique link to the source code is extracted from the server's response, which is placed on the clipboard.

public void Exec( string cmdName, vsCommandExecOption executeOption, ref object varIn,
ref object varOut, ref bool handled)
{

handled = false ;

if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
{
if (cmdName == string .Format( "{0}.{1}" , _addInInstance.ProgID, CommandName))
{
handled = true ;
if (!((TextSelection)_applicationObject.ActiveDocument.Selection).IsEmpty)
{
// parameters: name1=value1&name2=value2
var webRequest = (HttpWebRequest)WebRequest.Create(Url);

webRequest.ContentType = "application/x-www-form-urlencoded" ;
webRequest.Method = "POST" ;

// formatting request string from document type and selection
string request = string .Format(RequestParameters,
FileFormat[_applicationObject.ActiveDocument.Name.Split( '.' )[1]],
System.Web.HttpUtility.UrlEncode(((TextSelection)_applicationObject.ActiveDocument.Selection).Text));

Stream os = null ;

try
{ // send the POST
webRequest.ContentLength = request.Length; //Length of request to send
os = webRequest.GetRequestStream();
os.Write(System.Text. Encoding .GetEncoding( "windows-1251" ).GetBytes(request), 0, request.Length); //Send it
}
catch (WebException ex)
{
MessageBox.Show(ex.Message, "HttpPost: Request error" ,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (os != null )
{
os.Close();
}
}

try
{ // get the response
var webResponse = (HttpWebResponse)webRequest.GetResponse();
if (webResponse != null )
{ // copy to clipboard
Clipboard.SetText(webResponse.ResponseUri.ToString());
MessageBox.Show( "Upload successfully. Url is copied in your clipboard." );
}
}
catch (WebException ex)
{
MessageBox.Show(ex.Message, "HttpPost: Response error" ,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}


* This source code was highlighted with Source Code Highlighter .


The file also ends with an unremarkable standard QueryStatus function.

Appendix A.
1. The contents of the main file Connect.cs
2. The contents of the auxiliary file ImageConverter.cs
The above sources are added to the site using the plugin described in the article.

Appendix B.
Files to article
The files PasteBin.AddIn and PasteBin.dll must be placed in the% USERPROFILE% \ My Documents \ Visual Studio 2008 \ Addins directory. 2008 can be replaced by 2005.

Source: https://habr.com/ru/post/80716/


All Articles