Visual Studio 2005,2008上で選択されたテキストでGoogle検索するAddin

http://d.hatena.ne.jp/m-tanaka/20080227
昨日の続き。


せっかくなので、VS2005 VS2008版もつくってみた。
VS2005とVS2008ではインストーラは作成されない。
かわりに、.AddInというXMLファイルが作成されるので、これと、ビルドされたdllを
My Documents\Visual Studio 2005\Addins
My Documents\Visual Studio 2008\Addins
に置く。
http://msdn2.microsoft.com/ja-jp/library/19dax6cz(VS.80).aspx


using System;
using Extensibility;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;
using System.Resources;
using System.Reflection;
using System.Globalization;
using System.Windows.Forms;
using System.Diagnostics;
using System.Web;

namespace Zero2005
{
	/// <summary>アドインを実装するためのオブジェクトです。</summary>
	/// <seealso class='IDTExtensibility2' />
	public class Connect : IDTExtensibility2, IDTCommandTarget
	{
		/// <summary>アドイン オブジェクトのコンストラクタを実装します。初期化コードをこのメソッド内に配置してください。</summary>
		public Connect()
		{
		}

		/// <summary>IDTExtensibility2 インターフェイスの OnConnection メソッドを実装します。アドインが読み込まれる際に通知を受けます。</summary>
		/// <param term='application'>ホスト アプリケーションのルート オブジェクトです。</param>
		/// <param term='connectMode'>アドインの読み込み状態を説明します。</param>
		/// <param term='addInInst'>このアドインを表すオブジェクトです。</param>
		/// <seealso class='IDTExtensibility2' />
		public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
		{
			_applicationObject = (DTE2)application;
			_addInInstance = (AddIn)addInInst;
			if(connectMode == ext_ConnectMode.ext_cm_UISetup)
			{
				object []contextGUIDS = new object[] { };
				Commands2 commands = (Commands2)_applicationObject.Commands;
				string toolsMenuName;

				try
				{
					//コマンドを別のメニューに移動するには、単語 "Tools" を英語版のメニューに変換してください。 
					//  このコードはカルチャを認識して、メニュー名に追加した後、コマンドをそのメニューに追加します。
					//  ファイル内にトップレベル メニューの一覧があります。
					//  CommandBar.resx.
					ResourceManager resourceManager = new ResourceManager("Zero2005.CommandBar", Assembly.GetExecutingAssembly());
					CultureInfo cultureInfo = new System.Globalization.CultureInfo(_applicationObject.LocaleID);
					string resourceName = String.Concat(cultureInfo.TwoLetterISOLanguageName, "Tools");
					toolsMenuName = resourceManager.GetString(resourceName);
				}
				catch
				{
					//単語 'Tools' の他言語バージョンを検索しましたが、見つかりませんでした。
					//  既定は en-US の単語ですが、現在のカルチャでも機能する可能性があります。
					toolsMenuName = "Tools";
				}

				//コマンドを [ツール] メニューに配置します。
				//メイン メニュー項目のすべてを保持するトップレベル コマンド バーである、MenuBar コマンド バーを検索します:
				Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"];

				//MenuBar コマンド バーで [ツール] コマンド バーを検索します:
				CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName];
				CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl;

				//アドインによって処理する複数のコマンドを追加する場合、この try ブロックおよび catch ブロックを重複できます。
				//  ただし、新しいコマンド名を含めるために QueryStatus メソッドおよび Exec メソッドの更新も実行してください。
				try
				{
					//コマンド コレクションにコマンドを追加します:
                    Command command = commands.AddNamedCommand2(_addInInstance, "GoogleSearch", "GoogleSearch", "Executes the command for Zero2005", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);

					//コマンドのコントロールを [ツール] メニューに追加します:
					if((command != null) && (toolsPopup != null))
					{
						command.AddControl(toolsPopup.CommandBar, 1);
					}
				}
				catch(System.ArgumentException)
				{
					//同じ名前のコマンドが既に存在しているため、例外が発生した可能性があります。
					//  その場合、コマンドを再作成する必要はありません。 例外を 
                    //  無視しても安全です。
				}
			}
		}

		/// <summary>IDTExtensibility2 インターフェイスの OnDisconnection メソッドを実装します。アドインがアンロードされる際に通知を受けます。</summary>
		/// <param term='disconnectMode'>アドインのアンロード状態を説明します。</param>
		/// <param term='custom'>ホスト アプリケーション固有のパラメータの配列です。</param>
		/// <seealso class='IDTExtensibility2' />
		public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
		{
		}

		/// <summary>IDTExtensibility2 インターフェイスの OnAddInsUpdate メソッドを実装します。アドインのコレクションが変更されたときに通知を受けます。</summary>
		/// <param term='custom'>ホスト アプリケーション固有のパラメータの配列です。</param>
		/// <seealso class='IDTExtensibility2' />		
		public void OnAddInsUpdate(ref Array custom)
		{
		}

		/// <summary>IDTExtensibility2 インターフェイスの OnStartupComplete メソッドを実装します。ホスト アプリケーションが読み込みを終了したときに通知を受けます。</summary>
		/// <param term='custom'>ホスト アプリケーション固有のパラメータの配列です。</param>
		/// <seealso class='IDTExtensibility2' />
		public void OnStartupComplete(ref Array custom)
		{
		}

		/// <summary>IDTExtensibility2 インターフェイスの OnBeginShutdown メソッドを実装します。ホスト アプリケーションがアンロードされる際に通知を受けます。</summary>
		/// <param term='custom'>ホスト アプリケーション固有のパラメータの配列です。</param>
		/// <seealso class='IDTExtensibility2' />
		public void OnBeginShutdown(ref Array custom)
		{
		}
		
		/// <summary>IDTCommandTarget インターフェイスの QueryStatus メソッドを実装します。これは、コマンドの可用性が更新されたときに呼び出されます。</summary>
		/// <param term='commandName'>状態を決定するためのコマンド名です。</param>
		/// <param term='neededText'>コマンドに必要なテキストです。</param>
		/// <param term='status'>ユーザー インターフェイス内のコマンドの状態です。</param>
		/// <param term='commandText'>neededText パラメータから要求されたテキストです。</param>
		/// <seealso class='Exec' />
		public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText)
		{
			if(neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
			{
                if (commandName == "Zero2005.Connect.GoogleSearch")
				{
					status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
					return;
				}
			}
		}

		/// <summary>IDTCommandTarget インターフェイスの Exec メソッドを実装します。これは、コマンドが実行されるときに呼び出されます。</summary>
		/// <param term='commandName'>実行するコマンド名です。</param>
		/// <param term='executeOption'>コマンドの実行方法を説明します。</param>
		/// <param term='varIn'>呼び出し元からコマンド ハンドラへ渡されたパラメータです。</param>
		/// <param term='varOut'>コマンド ハンドラから呼び出し元へ渡されたパラメータです。</param>
		/// <param term='handled'>コマンドが処理されたかどうかを呼び出し元に通知します。</param>
		/// <seealso class='Exec' />
		public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
		{
			handled = false;
			if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
			{
                if (commandName == "Zero2005.Connect.GoogleSearch")
				{
                    string selected = GetSelectedString();
                    if (selected != null && selected != string.Empty)
                    {
                        selected = HttpUtility.UrlEncode(selected);

                        ProcessStartInfo pi = new ProcessStartInfo(@"C:\Program Files\Internet Explorer\iexplore.exe", "http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4GFRC_jaJP205JP205&q=" + selected);
                        pi.UseShellExecute = false;

                        System.Diagnostics.Process p = new System.Diagnostics.Process();
                        p.StartInfo = pi;
                        p.Start();
                    }

                    handled = true;
                    return;
				}
			}
		}
		private DTE2 _applicationObject;
		private AddIn _addInInstance;

        private string GetSelectedString()
        {
            string selectedString = null;

            if (_applicationObject.ActiveDocument.Selection != null)
            {
                TextDocument textDocument = _applicationObject.ActiveDocument.Object("TextDocument") as TextDocument;
                if (textDocument != null)
                {
                    TextSelection selection = textDocument.Selection;
                    if (selection != null)
                    {
                        selectedString = selection.Text;
                    }
                }
            }

            return selectedString;

        }
	}
}