Visual Studio是美国微软公司开发的一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE)等等,且所写的目标代码适用于微软支持的所有平台.可以说.NET开发人员离不开它,它可以极大的提高编写软件的效率. Visual Studio作为一个世界级开发工具,当然支持通过插件方式对其功能进行扩展,开发人员可以定制自己的插件来进一步提升Visual Studio的功能.
1 什么是Add In?
所谓的add-in就是一些被Visual Studio加载到内存中运行的,能给用户提供特定功能的DLL动态链接库. 对于一般的开发情景来说,最常见的add-in用法就是可以通过.NET语言访问 DTE2 对象. DTE2是Visual Studio Automation Model的顶层对象,它具有一组接口和对象可以与 Visual Studio进行交互.DTE2可以做以下这些事情:
- 访问和调用Visual Studio内置的函数和对象
- 执行编译
- 遍历解决方案中的项目
- 在Visual Studio IDE中定制UI
- 扩展Visual Studio功能...
2 创建VS Add In项目
用Visual Studio 2012创建名为MyVisualStudioAddin的项目(根据向导进行设置,这里不赘述),界面如下:
3 核心 Connect 类
插件入口就是Connect 类,先看一下Connect的类图:
- Connect 实现外接程序对象的构造函数。请将您的初始化代码置于此方法内。
- OnConnection 实现 IDTExtensibility2 接口的 OnConnection 方法。接收正在加载外接程序的通知。
- OnDisconnection 实现 IDTExtensibility2 接口的 OnDisconnection 方法。接收正在卸载外接程序的通知。
- OnAddInsUpdate 实现 IDTExtensibility2 接口的 OnAddInsUpdate 方法。当外接程序集合已发生更改时接收通知。
- OnStartupComplete 实现 IDTExtensibility2 接口的 OnStartupComplete 方法。接收宿主应用程序已完成加载的通知。
- OnBeginShutdown 实现 IDTExtensibility2 接口的 OnBeginShutdown 方法。接收正在卸载宿主应用程序的通知。
- QueryStatus 实现 IDTCommandTarget 接口的 QueryStatus 方法。此方法在更新该命令的可用性时调用。
- Exec 实现 IDTCommandTarget 接口的 Exec 方法。此方法在调用该命令时调用。
- _applicationObject 是DTE2实例,是宿主应用程序的根对象。
- _addInInstance是当前插件实例,表示此外接程序的对象。
首先定义一些内部的对象,主要是自定义的命令,如下所示:
1 ///用于实现外接程序的对象。 2 ///3 public class Connect : IDTExtensibility2, IDTCommandTarget 4 { 5 #region 命令定义 除了FindInSolutionExplorer外,此处的命令不是根据功能来命令的,而是根据命令所出现的位置来命令的 6 private readonly string MY_COMMAND_FindInSolutionExplorer = "FindInSolutionExplorer"; 7 private readonly string MY_COMMAND_Project = "cmdInProject";//在项目上 8 private readonly string MY_COMMAND_Solution = "cmdInSolution";//在解决方案上 9 private readonly string MY_COMMAND_MenuBar = "cmdInMenuBar";//在菜单栏上10 private readonly string MY_COMMAND_CodeWindow = "cmdInCodeWindow";//代码窗口11 private readonly string MY_COMMAND_Files = "cmdInFiles";12 #endregion13 14 private Command findCommand = null;15 private CommandBarButton findCommandBarButtonButton = null;16 private AddInLogger logger = null;17 18 private DTE2 _applicationObject;19 private EnvDTE.AddIn _addInInstance;20 ......21 }
初始化插件UI的代码:
1 public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom) 2 { 3 4 _applicationObject = (DTE2)application; 5 _addInInstance = (AddIn)addInInst; 6 7 8 if (connectMode == ext_ConnectMode.ext_cm_UISetup) 9 {10 object[] contextGUIDS = new object[] { };11 Commands2 commands = (Commands2)_applicationObject.Commands;12 string toolsMenuName = "Tools";13 14 //将此命令置于“工具”菜单上。15 //查找 MenuBar 命令栏,该命令栏是容纳所有主菜单项的顶级命令栏:16 Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"];17 18 //在 MenuBar 命令栏上查找“工具”命令栏:19 CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName];20 CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl;21 22 //如果希望添加多个由您的外接程序处理的命令,可以重复此 try/catch 块,23 // 只需确保更新 QueryStatus/Exec 方法,使其包含新的命令名。24 try25 {26 //将一个命令添加到 Commands 集合:27 Command command = commands.AddNamedCommand2(_addInInstance, "MyVisualStudioAddin", "MyVS外接程序", "Executes the command for MyVisualStudioAddin", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);28 29 //将对应于该命令的控件添加到“工具”菜单:30 if ((command != null) && (toolsPopup != null))31 {32 command.AddControl(toolsPopup.CommandBar, 1);33 }34 }35 catch (System.ArgumentException)36 {37 //如果出现此异常,原因很可能是由于具有该名称的命令38 // 已存在。如果确实如此,则无需重新创建此命令,并且39 // 可以放心忽略此异常。40 }41 42 43 44 bool logtoOutputWindow = System.Diagnostics.Debugger.IsAttached;45 logger = new AddInLogger((DTE)_applicationObject, "MyVisualStudioAddin", logtoOutputWindow);46 logger.LogMessage(string.Format("OnConnection() called with connectMode: '{0}'", connectMode));47 try48 {49 switch (connectMode)50 {51 case ext_ConnectMode.ext_cm_UISetup:52 // We should never get here, this is temporary UI53 AddAddInUI();54 break;55 56 case ext_ConnectMode.ext_cm_Startup:57 // The add-in was marked to load on startup58 AddAddInUI();59 break;60 61 case ext_ConnectMode.ext_cm_AfterStartup:62 // The add-in was loaded by hand after startup using the Add-In Manager63 // Initialize it in the same way that when is loaded on startup64 AddAddInUI();65 break;66 }67 }68 catch (Exception ex)69 {70 logger.LogError(ex.ToString());71 }72 73 74 }75 }
1 ///2 /// 设置插件UI 3 /// 4 private void AddAddInUI() 5 { 6 #region 获取CommandBars的名称 7 //CommandBars commandBars = (CommandBars)applicationObject.CommandBars; 8 //System.Text.StringBuilder sb = new System.Text.StringBuilder(); 9 10 //foreach (CommandBar cbar in commandBars) 11 //{ 12 // sb.AppendLine(cbar.Name); 13 //} 14 15 //System.Windows.Forms. Clipboard.SetText(sb.ToString()); 16 17 #region name 18 // MenuBar 19 //Standard 20 //Build 21 //Context Menus 22 //Data Design 23 //Formatting 24 //Style Application 25 //HTML Source Editing 26 //Class Designer Toolbar 27 //Text Editor 28 //Workflow 29 //Dialog Editor 30 //Image Editor 31 //Style Sheet 32 //Source Control 33 //Recorder 34 //Microsoft XML Editor 35 //Query Designer 36 //View Designer 37 //Database Diagram 38 //Table Designer 39 //Layout 40 //Help 41 //Debug Location 42 //Debug 43 //Report Formatting 44 //Report Borders 45 //Device 46 //Microsoft Office Excel 2007 47 //Microsoft Office Excel 2003 48 //Microsoft Office Word 2007 49 //Microsoft Office Word 2003 50 //Test Tools 51 //CrystalReportMain 52 //CrystalReportInsert 53 //ClearCase - Base 54 //ClearCase - UCM 55 //Error List 56 //Docked Window 57 //Menu Designer 58 //Properties Window 59 //Toolbox 60 //Task List 61 //Results List 62 //Stub Project 63 //No Commands Available 64 //Command Window 65 //AutoHidden Windows 66 //Expansion Manager 67 //Find Regular Expression Builder 68 //Replace Regular Expression Builder 69 //Wild Card Expression Builder 70 //Wild Card Expression Builder 71 //External Tools Arguments 72 //External Tools Directories 73 //Easy MDI Tool Window 74 //Easy MDI Document Window 75 //Easy MDI Dragging 76 //Open Drop Down 77 //Object Browser Objects Pane 78 //Object Browser Members Pane 79 //Object Browser Description Pane 80 //Find Symbol 81 //Drag and Drop 82 //Bookmark Window 83 //Error Correction 84 //EzMDI Files 85 //Ca&ll Browser 86 //Preview Changes 87 //Discover Service References 88 //Smart Tag 89 //Editor Context Menus 90 //Class View Context Menus 91 //Debugger Context Menus 92 //Project and Solution Context Menus 93 //Other Context Menus 94 //Sort By 95 //Show Columns 96 //Implement Interface 97 //Resolve 98 //Refactor 99 //Organize Usings100 //Create Private Accessor101 //Class View Multi-select Project references Items102 //Class View Multi-select Project references members103 //Class View Project104 //Class View Item105 //Class View Folder106 //Class View Grouping Folder107 //Class View Multi-select108 //Class View Multi-select members109 //Class View Member110 //Class View Grouping Members111 //Class View Project References Folder112 //Class View Project Reference113 //Class View Project Reference Item114 //Class View Project Reference Member115 //Project116 //Solution Folder117 //Cross Project Solution Project118 //Cross Project Solution Item119 //Cross Project Project Item120 //Cross Project Multi Project121 //Cross Project Multi Item122 //Cross Project Multi Solution Folder123 //Cross Project Multi Project/Folder124 //Item125 //Folder126 //Reference Root127 //Reference Item128 //Web Reference Folder129 //App Designer Folder130 //Web Project Folder131 //Web Folder132 //Web Item133 //Web SubWeb134 //References135 //Misc Files Project136 //Solution137 //Code Window138 //XAML Editor139 //Surface140 //DataSourceContext141 //DbTableContext142 //DataTableContext143 //RelationContext144 //FunctionContext145 //ColumnContext146 //QueryContext147 //DataAccessorContext148 //Context149 //Basic Context150 //Context151 //Context152 //Context153 //HTML Context154 //Script Context155 //ASPX Context156 //ASAX Context157 //ASPX Code Context158 //ASAX Code Context159 //ASPX VB Code Context160 //ASAX VB Code Context161 //ASMX Code Context162 //ASMX VB Code Context163 //Change &View164 //Static Node165 //Object Node166 //Multiple Static Nodes167 //Multiple Homogenous Object Nodes168 //Multiple Heterogenous Object Nodes169 //Multiple Heterogenous Nodes170 //Add &New171 //Selection172 //Container173 //TraySelection174 //Document Outline175 //Component Tray176 //Propertysheet177 //Configuration178 //Project179 //Multi-Select180 //System Propertysheet181 //Topic Menu182 //Topic Source Menu183 //Favorites Window Context Menu184 //Data Sources185 //Server Explorer186 //Managed Resources Editor Context Menu187 //Settings Designer188 //My Extensibility189 //Class Designer Context Menu190 //Class Diagram Context Menu191 //Class Details Context Menu192 //Selection193 //&Zoom194 //Page Layout195 //Designer Actions196 //&Navigation Tools197 //Resource View198 //Resource Editors199 //Resource Dialog Editors200 //Binary Editor201 //CSSDocOutline202 //CSSSource203 //Checkin Dialog Context Menu204 //Pending Checkin Window Context Menu205 //Standard TreeGrid context menu206 //GetVersion Dialog Context Menu207 //Check Out Dialog Context Menu208 //Macro209 //Module210 //Project211 //Root212 //TocContext213 //ResListContext214 //Query Diagram Pane215 //Query Diagram Table216 //Query Diagram Table Column217 //Query Diagram Join Line218 //Query Diagram Multi-select219 //Query Grid Pane220 //Query SQL Pane221 //Query Results Pane222 //Database Designer223 //Database Designer Table224 //Database Designer Relationship225 //Text Annotation226 //Database Project227 //DB Project Connection228 //DB Project Folder229 //Database References Folder230 //Folders231 //DB Project File232 //Query233 //Script234 //Database Reference Node235 //Files236 //Multi-select237 //PropertyBrowser238 //Editor239 //Script Outline240 //DefaultContext241 //ImageContext242 //SelectionContext243 //AnchorContext244 //Step Into Specific245 //Autos Window246 //Breakpoint247 //Load Symbols From248 //Breakpoints Window249 //Call Stack Window250 //Thread Tip Window251 //Data Tip Window252 //Disassembly Window253 //Locals Window254 //Memory Window255 //Modules Window256 //Output Window257 //Processes Window258 //Registers Window259 //Threads Window260 //Watch Window261 //Script Project262 //Thread IP Marker263 //Thread IP Markers264 //Control265 //Report266 //Row/Column267 //Cell268 //Field Chooser269 //Row/Column270 //Chart271 //Registry272 //File System273 //File System274 //File Types275 //User Interface276 //Launch Conditions277 //Custom Actions278 //New279 //Add280 //Add Special Folder281 //View282 //Project Node283 //A&dd284 //Cab Project Node285 //A&dd286 //File nodes287 //Dep. file nodes288 //Assembly nodes289 //Dep. assembly nodes290 //MSM nodes291 //Dep. MSM nodes292 //Output nodes293 //Simple file nodes294 //Simple output nodes295 //Dependency node296 //Multiple selections297 //Dep. Multiple selections298 //View299 //Editor300 //ORDesigner Context Menu301 //ORDesigner Context Menu302 //ORDesigner Context Menu303 //OTBObjCtxtMenu304 //SIDE Left Pane Context Menu305 //SIDE CertMgr Context Menu306 //Registry307 //File System308 //File System309 //New310 //Add311 //Add Special Folder312 //View313 //Project Node314 //A&dd315 //Cab Project Node316 //A&dd317 //File nodes318 //Dep. file nodes319 //Assembly nodes320 //Dep. assembly nodes321 //MSM nodes322 //Dep. MSM nodes323 //Output nodes324 //Dependency node325 //Multiple selections326 //Dep. Multiple selections327 //View328 //AppNet Designer Context329 //AppNet Project Node Context330 //Exe Project331 //Debug332 //Test Results Context Menu333 //Test List Editor Context Menu334 //Test List Context Menu335 //Test Run Context Menu336 //View Context Menu337 //Group338 //Database339 //Edit Text340 //Formula Parameter341 //Section342 //Default343 //Object Selection344 //Insert to Report345 //SchemaExplorer346 //AddNewItem347 //MicrosoftDataEntityDesign Context348 //MicrosoftDataEntityDesign Context349 //Find Checkouts350 //Pending Solution Checkins351 //Views Folder item context menu352 //UCM Project item context menu353 //View item context menu354 //Solution item context menu355 //Deliver356 //Rebase357 //ClearCase search Context Menus358 //System359 360 #endregion361 #endregion362 //------------------------------Code Window------------------------------------------------------363 object[] contextUIGuids = new object[] { };364 Commands2 commands = (Commands2)_applicationObject.Commands;365 try366 {367 findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_CodeWindow), -1);368 }369 catch370 {371 // command doesn't exist372 }373 374 if (findCommand == null)375 {376 findCommand = commands.AddNamedCommand2(377 _addInInstance,378 MY_COMMAND_CodeWindow,379 MY_COMMAND_CodeWindow,380 MY_COMMAND_CodeWindow,381 false,382 MyVisualStudioAddin.Properties.Resources._default,383 ref contextUIGuids,384 (int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));385 }386 387 CommandBars cmdBars = (CommandBars)_applicationObject.CommandBars;388 389 if (findCommand != null)390 {391 // Add a button to the code window context window392 //代码393 CommandBar codeWindowCommandBar = cmdBars["Code Window"];394 //Project395 //Solution Folder396 if (codeWindowCommandBar != null)397 {398 findCommandBarButtonButton = (CommandBarButton)findCommand.AddControl(399 codeWindowCommandBar, codeWindowCommandBar.Controls.Count + 1);400 findCommandBarButtonButton.Caption = "Code Window";401 }402 }403 404 //-------------------------------------project---------------------------------------------------------------405 findCommand = null;406 contextUIGuids = new object[] { };407 try408 {409 findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_Project), -1);410 }411 catch412 {413 // command doesn't exist414 }415 416 if (findCommand == null)417 {418 findCommand = commands.AddNamedCommand2(419 _addInInstance,420 MY_COMMAND_Project,421 MY_COMMAND_Project,422 MY_COMMAND_Project,423 false,424 MyVisualStudioAddin.Properties.Resources.man,425 ref contextUIGuids,426 (int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));427 }428 if (findCommand != null)429 {430 //项目431 CommandBar codeWindowCommandBar2 = cmdBars["Project"];432 //Solution Folder433 if (codeWindowCommandBar2 != null)434 {435 findCommandBarButtonButton = (CommandBarButton)findCommand.AddControl(436 codeWindowCommandBar2, codeWindowCommandBar2.Controls.Count + 1);437 findCommandBarButtonButton.Caption = "生成表结构类";438 }439 }440 //-----------------------------------------解决方案---------------------------------------------------------441 findCommand = null;442 contextUIGuids = new object[] { };443 try444 {445 findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_Solution), -1);446 }447 catch448 {449 // command doesn't exist450 }451 452 if (findCommand == null)453 {454 findCommand = commands.AddNamedCommand2(455 _addInInstance,456 MY_COMMAND_Solution,457 MY_COMMAND_Solution,458 MY_COMMAND_Solution,459 false,460 MyVisualStudioAddin.Properties.Resources.FindHS,461 ref contextUIGuids,462 (int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));463 }464 if (findCommand != null)465 {466 //解决方案467 CommandBar codeWindowCommandBar3 = cmdBars["Solution"];468 if (codeWindowCommandBar3 != null)469 {470 findCommandBarButtonButton = (CommandBarButton)findCommand.AddControl(471 codeWindowCommandBar3, codeWindowCommandBar3.Controls.Count + 1);472 findCommandBarButtonButton.Caption = "生成表结构类";473 }474 }475 //-------------------------------------------MenuBar-------------------------------------------------------476 findCommand = null;477 contextUIGuids = new object[] { };478 try479 {480 findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_MenuBar), -1);481 }482 catch483 {484 // command doesn't exist485 }486 487 if (findCommand == null)488 {489 findCommand = commands.AddNamedCommand2(490 _addInInstance,491 MY_COMMAND_MenuBar,492 MY_COMMAND_MenuBar,493 MY_COMMAND_MenuBar,494 false,495 MyVisualStudioAddin.Properties.Resources.man,496 ref contextUIGuids,497 (int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));498 }499 if (findCommand != null)500 {501 //menubar502 CommandBar codeWindowCommandBar4 = cmdBars["MenuBar"];503 if (codeWindowCommandBar4 != null)504 {505 findCommandBarButtonButton = (CommandBarButton)findCommand.AddControl(506 codeWindowCommandBar4, codeWindowCommandBar4.Controls.Count + 1);507 findCommandBarButtonButton.Caption = "JackWang";508 }509 510 }511 //--------------------------Files------------------------------512 findCommand = null;513 contextUIGuids = new object[] { };514 try515 {516 findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_Files), -1);517 }518 catch519 {520 // command doesn't exist521 }522 523 if (findCommand == null)524 {525 findCommand = commands.AddNamedCommand2(526 _addInInstance,527 MY_COMMAND_Files,528 MY_COMMAND_Files,529 MY_COMMAND_Files,530 false,531 MyVisualStudioAddin.Properties.Resources.man,532 ref contextUIGuids,533 (int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));534 }535 if (findCommand != null)536 {537 //menubar538 CommandBar codeWindowCommandBar4 = cmdBars["Item"];539 if (codeWindowCommandBar4 != null)540 {541 findCommandBarButtonButton = (CommandBarButton)findCommand.AddControl(542 codeWindowCommandBar4, codeWindowCommandBar4.Controls.Count + 1);543 findCommandBarButtonButton.Caption = "生成表结构类";544 }545 546 }547 548 549 550 }
1 public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText) 2 { 3 try 4 { 5 if (neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone) 6 { 7 if (commandName == "MyVisualStudioAddin.Connect.MyVisualStudioAddin") 8 { 9 status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;10 return;11 }12 13 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_FindInSolutionExplorer))14 {15 Solution solution = _applicationObject.Solution;16 status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;17 return;18 }19 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_CodeWindow))20 {21 Solution solution = _applicationObject.Solution;22 status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;23 return;24 }25 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_MenuBar))26 {27 Solution solution = _applicationObject.Solution;28 status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;29 return;30 }31 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Project))32 {33 Solution solution = _applicationObject.Solution;34 status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;35 return;36 }37 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Solution))38 {39 Solution solution = _applicationObject.Solution;40 status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;41 return;42 }43 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Files))44 {45 Solution solution = _applicationObject.Solution;46 status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;47 return;48 }49 }50 }51 catch (Exception ex)52 {53 logger.LogError(ex.ToString());54 }55 }
1 public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled) 2 { 3 try 4 { 5 handled = false; 6 if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault) 7 { 8 //命名空间.Connect.命名 9 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_FindInSolutionExplorer))10 {11 FindCurrentActiveDocumentInSolutionExplorer();12 handled = true;13 return;14 }15 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_CodeWindow))16 {17 string fullpath = this.GetActiveProjectFullPath();18 if (fullpath != "")19 {20 POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);21 frm.Show();22 }23 handled = true;24 return;25 }26 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_MenuBar))27 {28 string fullpath = this.GetActiveProjectFullPath();29 if (fullpath != "")30 {31 POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);32 frm.Show();33 }34 handled = true;35 return;36 }37 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Project))38 {39 string fullpath = this.GetActiveProjectFullPath();40 if (fullpath != "")41 {42 POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);43 frm.Show();44 }45 46 handled = true;47 return;48 }49 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Solution))50 {51 string fullpath = this.GetActiveProjectFullPath();52 if (fullpath != "")53 {54 POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);55 frm.Show();56 }57 handled = true;58 return;59 }60 if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Files))61 {62 string fullpath = this.GetActiveProjectFullPath();63 if (fullpath != "")64 {65 POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);66 frm.Show();67 }68 handled = true;69 return;70 }71 72 if (commandName == "MyVisualStudioAddin.Connect.MyVisualStudioAddin")73 {74 string fullpath = this.GetActiveProjectFullPath();75 if (fullpath != "")76 {77 POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);78 frm.Show();79 }80 handled = true;81 return;82 }83 84 85 }86 }87 catch (Exception ex)88 {89 logger.LogError(ex.ToString());90 }91 92 }
获取当前IDE激活项目的路径:
1 ///2 /// Gets the Active project FullPath 3 /// 4 ///5 public string GetActiveProjectFullPath() 6 { 7 // Returns the name of the currently selected project in the solution. 8 Project proj = getActiveProject(); 9 if (proj!=null)10 {11 string fullPath = proj.Properties.Item("FullPath").Value.ToString();12 return fullPath;13 // return proj.FullName;14 }15 return "";16 17 }18 /// 19 /// Gets the Active project20 /// 21 ///22 public Project getActiveProject()23 {24 Array projects = (Array)_applicationObject.ActiveSolutionProjects;25 if (projects != null && projects.Length > 0)26 {27 return projects.GetValue(0) as Project;28 }29 projects = (Array)_applicationObject.Solution.SolutionBuild.StartupProjects;30 if (projects != null && projects.Length >= 1)31 {32 return projects.GetValue(0) as Project;33 }34 projects = (Array)_applicationObject.Solution.Projects;35 if (projects != null && projects.Length > 0)36 {37 return projects.GetValue(0) as Project;38 }39 return null;40 }
关于如何根据数据库结构生成C# Code代码,可以参加.
4 插件发布
创建了外接程序后,必须先向 Visual Studio 注册此外接程序,然后才能在“外接程序管理器”中激活它。 使用具有 .addin 文件扩展名的 XML 文件来完成此操作。.addin 文件描述了 Visual Studio 在“外接程序管理器”中显示外接程序所需的信息。 在 Visual Studio 启动时,它会查找 .addin 文件位置,获取任何可用的 .addin 文件。 如果找到相应文件,则会读取 XML 文件并向“外接程序管理器”提供在单击外接程序进行启动时所需的信息。使用外接程序向导创建外接程序时,会自动创建一个 .addin 文件。 你也可以使用本主题中的信息手动创建 .addin 文件。我是用Visual Studio2012 所以将.addin文件和对应的dll拷贝到C:\Users\wangming\Documents\Visual Studio 2012\Addins文件下:
如果发布没有错误,那么重新启动Visual Studio2012后,在项目文件上右击弹出菜单,可以看到下面的界面:
同时在菜单栏创建了一个JackWang的命令按钮和工具菜单下还添加了一个MyVS外接程序的命令按钮,如下图:
5 代码生成器
代码生成器(此处用的是 可以根据用户选择的数据库,选择对应的表,然后生成表结构对应的C#类:
6 插件卸载
如果自己定义的插件想卸载怎么办?可参见https://msdn.microsoft.com/en-us/library/ms228765.aspx.
-
删除插件对应的.addin文件. 默认路径为..\Users\username\My Documents\Visual Studio 2012\Addins\(请根据实际情况查看具体路径)
-
在 Visual Studio开发人员命令行中, 输入devenv /resetaddin MyVisualStudioAddin.Connect 进行卸载(MyVisualStudioAddin.Connect 是MyVisualStudioAddin.AddIn文件中的FullClassName;
-
至此, add-in 不会出现在IDE中,卸载完成. 但是要完整去除必须手动删除插件对应的项目文件(如果你再次调试,可能会再次进行注册);
7 总结
通过插件机制可以方便的定制VS IDE, 一般软件公司都有自己的一套框架,其代码也有一定的封装,且各不相同,可以通过扩展VS,通过定制的代码生成工具来快速生成符合本公司所需的代码,从而从重复机械的劳动中解放出来(虽然完全自动生成的代码不可能直接能用,但是人工在此基础上进行调整,也提升了代码的编写效率,而且减少类似于拼写/标点等人为的错误点等.
虽然我们不生产代码,是代码的搬运工,但是正确的打开方式是用代码去帮我们搬运代码!!!