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 /// <summary>用于实现外接程序的对象。</summary> 2 /// <seealso class=‘IDTExtensibility2‘ /> 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 #endregion 13 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 try 25 { 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 try 48 { 49 switch (connectMode) 50 { 51 case ext_ConnectMode.ext_cm_UISetup: 52 // We should never get here, this is temporary UI 53 AddAddInUI(); 54 break; 55 56 case ext_ConnectMode.ext_cm_Startup: 57 // The add-in was marked to load on startup 58 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 Manager 63 // Initialize it in the same way that when is loaded on startup 64 AddAddInUI(); 65 break; 66 } 67 } 68 catch (Exception ex) 69 { 70 logger.LogError(ex.ToString()); 71 } 72 73 74 } 75 }
1 /// <summary> 2 /// 设置插件UI 3 /// </summary> 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 Usings 100 //Create Private Accessor 101 //Class View Multi-select Project references Items 102 //Class View Multi-select Project references members 103 //Class View Project 104 //Class View Item 105 //Class View Folder 106 //Class View Grouping Folder 107 //Class View Multi-select 108 //Class View Multi-select members 109 //Class View Member 110 //Class View Grouping Members 111 //Class View Project References Folder 112 //Class View Project Reference 113 //Class View Project Reference Item 114 //Class View Project Reference Member 115 //Project 116 //Solution Folder 117 //Cross Project Solution Project 118 //Cross Project Solution Item 119 //Cross Project Project Item 120 //Cross Project Multi Project 121 //Cross Project Multi Item 122 //Cross Project Multi Solution Folder 123 //Cross Project Multi Project/Folder 124 //Item 125 //Folder 126 //Reference Root 127 //Reference Item 128 //Web Reference Folder 129 //App Designer Folder 130 //Web Project Folder 131 //Web Folder 132 //Web Item 133 //Web SubWeb 134 //References 135 //Misc Files Project 136 //Solution 137 //Code Window 138 //XAML Editor 139 //Surface 140 //DataSourceContext 141 //DbTableContext 142 //DataTableContext 143 //RelationContext 144 //FunctionContext 145 //ColumnContext 146 //QueryContext 147 //DataAccessorContext 148 //Context 149 //Basic Context 150 //Context 151 //Context 152 //Context 153 //HTML Context 154 //Script Context 155 //ASPX Context 156 //ASAX Context 157 //ASPX Code Context 158 //ASAX Code Context 159 //ASPX VB Code Context 160 //ASAX VB Code Context 161 //ASMX Code Context 162 //ASMX VB Code Context 163 //Change &View 164 //Static Node 165 //Object Node 166 //Multiple Static Nodes 167 //Multiple Homogenous Object Nodes 168 //Multiple Heterogenous Object Nodes 169 //Multiple Heterogenous Nodes 170 //Add &New 171 //Selection 172 //Container 173 //TraySelection 174 //Document Outline 175 //Component Tray 176 //Propertysheet 177 //Configuration 178 //Project 179 //Multi-Select 180 //System Propertysheet 181 //Topic Menu 182 //Topic Source Menu 183 //Favorites Window Context Menu 184 //Data Sources 185 //Server Explorer 186 //Managed Resources Editor Context Menu 187 //Settings Designer 188 //My Extensibility 189 //Class Designer Context Menu 190 //Class Diagram Context Menu 191 //Class Details Context Menu 192 //Selection 193 //&Zoom 194 //Page Layout 195 //Designer Actions 196 //&Navigation Tools 197 //Resource View 198 //Resource Editors 199 //Resource Dialog Editors 200 //Binary Editor 201 //CSSDocOutline 202 //CSSSource 203 //Checkin Dialog Context Menu 204 //Pending Checkin Window Context Menu 205 //Standard TreeGrid context menu 206 //GetVersion Dialog Context Menu 207 //Check Out Dialog Context Menu 208 //Macro 209 //Module 210 //Project 211 //Root 212 //TocContext 213 //ResListContext 214 //Query Diagram Pane 215 //Query Diagram Table 216 //Query Diagram Table Column 217 //Query Diagram Join Line 218 //Query Diagram Multi-select 219 //Query Grid Pane 220 //Query SQL Pane 221 //Query Results Pane 222 //Database Designer 223 //Database Designer Table 224 //Database Designer Relationship 225 //Text Annotation 226 //Database Project 227 //DB Project Connection 228 //DB Project Folder 229 //Database References Folder 230 //Folders 231 //DB Project File 232 //Query 233 //Script 234 //Database Reference Node 235 //Files 236 //Multi-select 237 //PropertyBrowser 238 //Editor 239 //Script Outline 240 //DefaultContext 241 //ImageContext 242 //SelectionContext 243 //AnchorContext 244 //Step Into Specific 245 //Autos Window 246 //Breakpoint 247 //Load Symbols From 248 //Breakpoints Window 249 //Call Stack Window 250 //Thread Tip Window 251 //Data Tip Window 252 //Disassembly Window 253 //Locals Window 254 //Memory Window 255 //Modules Window 256 //Output Window 257 //Processes Window 258 //Registers Window 259 //Threads Window 260 //Watch Window 261 //Script Project 262 //Thread IP Marker 263 //Thread IP Markers 264 //Control 265 //Report 266 //Row/Column 267 //Cell 268 //Field Chooser 269 //Row/Column 270 //Chart 271 //Registry 272 //File System 273 //File System 274 //File Types 275 //User Interface 276 //Launch Conditions 277 //Custom Actions 278 //New 279 //Add 280 //Add Special Folder 281 //View 282 //Project Node 283 //A&dd 284 //Cab Project Node 285 //A&dd 286 //File nodes 287 //Dep. file nodes 288 //Assembly nodes 289 //Dep. assembly nodes 290 //MSM nodes 291 //Dep. MSM nodes 292 //Output nodes 293 //Simple file nodes 294 //Simple output nodes 295 //Dependency node 296 //Multiple selections 297 //Dep. Multiple selections 298 //View 299 //Editor 300 //ORDesigner Context Menu 301 //ORDesigner Context Menu 302 //ORDesigner Context Menu 303 //OTBObjCtxtMenu 304 //SIDE Left Pane Context Menu 305 //SIDE CertMgr Context Menu 306 //Registry 307 //File System 308 //File System 309 //New 310 //Add 311 //Add Special Folder 312 //View 313 //Project Node 314 //A&dd 315 //Cab Project Node 316 //A&dd 317 //File nodes 318 //Dep. file nodes 319 //Assembly nodes 320 //Dep. assembly nodes 321 //MSM nodes 322 //Dep. MSM nodes 323 //Output nodes 324 //Dependency node 325 //Multiple selections 326 //Dep. Multiple selections 327 //View 328 //AppNet Designer Context 329 //AppNet Project Node Context 330 //Exe Project 331 //Debug 332 //Test Results Context Menu 333 //Test List Editor Context Menu 334 //Test List Context Menu 335 //Test Run Context Menu 336 //View Context Menu 337 //Group 338 //Database 339 //Edit Text 340 //Formula Parameter 341 //Section 342 //Default 343 //Object Selection 344 //Insert to Report 345 //SchemaExplorer 346 //AddNewItem 347 //MicrosoftDataEntityDesign Context 348 //MicrosoftDataEntityDesign Context 349 //Find Checkouts 350 //Pending Solution Checkins 351 //Views Folder item context menu 352 //UCM Project item context menu 353 //View item context menu 354 //Solution item context menu 355 //Deliver 356 //Rebase 357 //ClearCase search Context Menus 358 //System 359 360 #endregion 361 #endregion 362 //------------------------------Code Window------------------------------------------------------ 363 object[] contextUIGuids = new object[] { }; 364 Commands2 commands = (Commands2)_applicationObject.Commands; 365 try 366 { 367 findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_CodeWindow), -1); 368 } 369 catch 370 { 371 // command doesn‘t exist 372 } 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 window 392 //代码 393 CommandBar codeWindowCommandBar = cmdBars["Code Window"]; 394 //Project 395 //Solution Folder 396 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 try 408 { 409 findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_Project), -1); 410 } 411 catch 412 { 413 // command doesn‘t exist 414 } 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 Folder 433 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 try 444 { 445 findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_Solution), -1); 446 } 447 catch 448 { 449 // command doesn‘t exist 450 } 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 try 479 { 480 findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_MenuBar), -1); 481 } 482 catch 483 { 484 // command doesn‘t exist 485 } 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 //menubar 502 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 try 515 { 516 findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_Files), -1); 517 } 518 catch 519 { 520 // command doesn‘t exist 521 } 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 //menubar 538 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 }
View Exec Code
获取当前IDE激活项目的路径:
1 /// <summary> 2 /// Gets the Active project FullPath 3 /// </summary> 4 /// <returns></returns> 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 /// <summary> 19 /// Gets the Active project 20 /// </summary> 21 /// <returns></returns> 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 代码生成器
代码生成器(此处用的是yuvalsol的工程,我将其整合到插件中)可以根据用户选择的数据库,选择对应的表,然后生成表结构对应的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,通过定制的代码生成工具来快速生成符合本公司所需的代码,从而从重复机械的劳动中解放出来(虽然完全自动生成的代码不可能直接能用,但是人工在此基础上进行调整,也提升了代码的编写效率,而且减少类似于拼写/标点等人为的错误点等.
虽然我们不生产代码,是代码的搬运工,但是正确的打开方式是用代码去帮我们搬运代码!!!