如何在Visual Studio中开发自己的代码生成器插件

时间:2023-03-08 19:04:47

   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的项目(根据向导进行设置,这里不赘述),界面如下:

如何在Visual Studio中开发自己的代码生成器插件

3 核心 Connect 类

  插件入口就是Connect 类,先看一下Connect的类图:

如何在Visual Studio中开发自己的代码生成器插件

  • 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是当前插件实例,表示此外接程序的对象。

  首先定义一些内部的对象,主要是自定义的命令,如下所示:

     /// <summary>用于实现外接程序的对象。</summary>
/// <seealso class='IDTExtensibility2' />
public class Connect : IDTExtensibility2, IDTCommandTarget
{
#region 命令定义 除了FindInSolutionExplorer外,此处的命令不是根据功能来命令的,而是根据命令所出现的位置来命令的
private readonly string MY_COMMAND_FindInSolutionExplorer = "FindInSolutionExplorer";
private readonly string MY_COMMAND_Project = "cmdInProject";//在项目上
private readonly string MY_COMMAND_Solution = "cmdInSolution";//在解决方案上
private readonly string MY_COMMAND_MenuBar = "cmdInMenuBar";//在菜单栏上
private readonly string MY_COMMAND_CodeWindow = "cmdInCodeWindow";//代码窗口
private readonly string MY_COMMAND_Files = "cmdInFiles";
#endregion private Command findCommand = null;
private CommandBarButton findCommandBarButtonButton = null;
private AddInLogger logger = null; private DTE2 _applicationObject;
private EnvDTE.AddIn _addInInstance;
     ......
}

  初始化插件UI的代码:

         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 = "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
{
//将一个命令添加到 Commands 集合:
Command command = commands.AddNamedCommand2(_addInInstance, "MyVisualStudioAddin", "MyVS外接程序", "Executes the command for MyVisualStudioAddin", true, , ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton); //将对应于该命令的控件添加到“工具”菜单:
if ((command != null) && (toolsPopup != null))
{
command.AddControl(toolsPopup.CommandBar, );
}
}
catch (System.ArgumentException)
{
//如果出现此异常,原因很可能是由于具有该名称的命令
// 已存在。如果确实如此,则无需重新创建此命令,并且
// 可以放心忽略此异常。
} bool logtoOutputWindow = System.Diagnostics.Debugger.IsAttached;
logger = new AddInLogger((DTE)_applicationObject, "MyVisualStudioAddin", logtoOutputWindow);
logger.LogMessage(string.Format("OnConnection() called with connectMode: '{0}'", connectMode));
try
{
switch (connectMode)
{
case ext_ConnectMode.ext_cm_UISetup:
// We should never get here, this is temporary UI
AddAddInUI();
break; case ext_ConnectMode.ext_cm_Startup:
// The add-in was marked to load on startup
AddAddInUI();
break; case ext_ConnectMode.ext_cm_AfterStartup:
// The add-in was loaded by hand after startup using the Add-In Manager
// Initialize it in the same way that when is loaded on startup
AddAddInUI();
break;
}
}
catch (Exception ex)
{
logger.LogError(ex.ToString());
} }
}
         /// <summary>
/// 设置插件UI
/// </summary>
private void AddAddInUI()
{
#region 获取CommandBars的名称
//CommandBars commandBars = (CommandBars)applicationObject.CommandBars;
//System.Text.StringBuilder sb = new System.Text.StringBuilder(); //foreach (CommandBar cbar in commandBars)
//{
// sb.AppendLine(cbar.Name);
//} //System.Windows.Forms. Clipboard.SetText(sb.ToString()); #region name
// MenuBar
//Standard
//Build
//Context Menus
//Data Design
//Formatting
//Style Application
//HTML Source Editing
//Class Designer Toolbar
//Text Editor
//Workflow
//Dialog Editor
//Image Editor
//Style Sheet
//Source Control
//Recorder
//Microsoft XML Editor
//Query Designer
//View Designer
//Database Diagram
//Table Designer
//Layout
//Help
//Debug Location
//Debug
//Report Formatting
//Report Borders
//Device
//Microsoft Office Excel 2007
//Microsoft Office Excel 2003
//Microsoft Office Word 2007
//Microsoft Office Word 2003
//Test Tools
//CrystalReportMain
//CrystalReportInsert
//ClearCase - Base
//ClearCase - UCM
//Error List
//Docked Window
//Menu Designer
//Properties Window
//Toolbox
//Task List
//Results List
//Stub Project
//No Commands Available
//Command Window
//AutoHidden Windows
//Expansion Manager
//Find Regular Expression Builder
//Replace Regular Expression Builder
//Wild Card Expression Builder
//Wild Card Expression Builder
//External Tools Arguments
//External Tools Directories
//Easy MDI Tool Window
//Easy MDI Document Window
//Easy MDI Dragging
//Open Drop Down
//Object Browser Objects Pane
//Object Browser Members Pane
//Object Browser Description Pane
//Find Symbol
//Drag and Drop
//Bookmark Window
//Error Correction
//EzMDI Files
//Ca&ll Browser
//Preview Changes
//Discover Service References
//Smart Tag
//Editor Context Menus
//Class View Context Menus
//Debugger Context Menus
//Project and Solution Context Menus
//Other Context Menus
//Sort By
//Show Columns
//Implement Interface
//Resolve
//Refactor
//Organize Usings
//Create Private Accessor
//Class View Multi-select Project references Items
//Class View Multi-select Project references members
//Class View Project
//Class View Item
//Class View Folder
//Class View Grouping Folder
//Class View Multi-select
//Class View Multi-select members
//Class View Member
//Class View Grouping Members
//Class View Project References Folder
//Class View Project Reference
//Class View Project Reference Item
//Class View Project Reference Member
//Project
//Solution Folder
//Cross Project Solution Project
//Cross Project Solution Item
//Cross Project Project Item
//Cross Project Multi Project
//Cross Project Multi Item
//Cross Project Multi Solution Folder
//Cross Project Multi Project/Folder
//Item
//Folder
//Reference Root
//Reference Item
//Web Reference Folder
//App Designer Folder
//Web Project Folder
//Web Folder
//Web Item
//Web SubWeb
//References
//Misc Files Project
//Solution
//Code Window
//XAML Editor
//Surface
//DataSourceContext
//DbTableContext
//DataTableContext
//RelationContext
//FunctionContext
//ColumnContext
//QueryContext
//DataAccessorContext
//Context
//Basic Context
//Context
//Context
//Context
//HTML Context
//Script Context
//ASPX Context
//ASAX Context
//ASPX Code Context
//ASAX Code Context
//ASPX VB Code Context
//ASAX VB Code Context
//ASMX Code Context
//ASMX VB Code Context
//Change &View
//Static Node
//Object Node
//Multiple Static Nodes
//Multiple Homogenous Object Nodes
//Multiple Heterogenous Object Nodes
//Multiple Heterogenous Nodes
//Add &New
//Selection
//Container
//TraySelection
//Document Outline
//Component Tray
//Propertysheet
//Configuration
//Project
//Multi-Select
//System Propertysheet
//Topic Menu
//Topic Source Menu
//Favorites Window Context Menu
//Data Sources
//Server Explorer
//Managed Resources Editor Context Menu
//Settings Designer
//My Extensibility
//Class Designer Context Menu
//Class Diagram Context Menu
//Class Details Context Menu
//Selection
//&Zoom
//Page Layout
//Designer Actions
//&Navigation Tools
//Resource View
//Resource Editors
//Resource Dialog Editors
//Binary Editor
//CSSDocOutline
//CSSSource
//Checkin Dialog Context Menu
//Pending Checkin Window Context Menu
//Standard TreeGrid context menu
//GetVersion Dialog Context Menu
//Check Out Dialog Context Menu
//Macro
//Module
//Project
//Root
//TocContext
//ResListContext
//Query Diagram Pane
//Query Diagram Table
//Query Diagram Table Column
//Query Diagram Join Line
//Query Diagram Multi-select
//Query Grid Pane
//Query SQL Pane
//Query Results Pane
//Database Designer
//Database Designer Table
//Database Designer Relationship
//Text Annotation
//Database Project
//DB Project Connection
//DB Project Folder
//Database References Folder
//Folders
//DB Project File
//Query
//Script
//Database Reference Node
//Files
//Multi-select
//PropertyBrowser
//Editor
//Script Outline
//DefaultContext
//ImageContext
//SelectionContext
//AnchorContext
//Step Into Specific
//Autos Window
//Breakpoint
//Load Symbols From
//Breakpoints Window
//Call Stack Window
//Thread Tip Window
//Data Tip Window
//Disassembly Window
//Locals Window
//Memory Window
//Modules Window
//Output Window
//Processes Window
//Registers Window
//Threads Window
//Watch Window
//Script Project
//Thread IP Marker
//Thread IP Markers
//Control
//Report
//Row/Column
//Cell
//Field Chooser
//Row/Column
//Chart
//Registry
//File System
//File System
//File Types
//User Interface
//Launch Conditions
//Custom Actions
//New
//Add
//Add Special Folder
//View
//Project Node
//A&dd
//Cab Project Node
//A&dd
//File nodes
//Dep. file nodes
//Assembly nodes
//Dep. assembly nodes
//MSM nodes
//Dep. MSM nodes
//Output nodes
//Simple file nodes
//Simple output nodes
//Dependency node
//Multiple selections
//Dep. Multiple selections
//View
//Editor
//ORDesigner Context Menu
//ORDesigner Context Menu
//ORDesigner Context Menu
//OTBObjCtxtMenu
//SIDE Left Pane Context Menu
//SIDE CertMgr Context Menu
//Registry
//File System
//File System
//New
//Add
//Add Special Folder
//View
//Project Node
//A&dd
//Cab Project Node
//A&dd
//File nodes
//Dep. file nodes
//Assembly nodes
//Dep. assembly nodes
//MSM nodes
//Dep. MSM nodes
//Output nodes
//Dependency node
//Multiple selections
//Dep. Multiple selections
//View
//AppNet Designer Context
//AppNet Project Node Context
//Exe Project
//Debug
//Test Results Context Menu
//Test List Editor Context Menu
//Test List Context Menu
//Test Run Context Menu
//View Context Menu
//Group
//Database
//Edit Text
//Formula Parameter
//Section
//Default
//Object Selection
//Insert to Report
//SchemaExplorer
//AddNewItem
//MicrosoftDataEntityDesign Context
//MicrosoftDataEntityDesign Context
//Find Checkouts
//Pending Solution Checkins
//Views Folder item context menu
//UCM Project item context menu
//View item context menu
//Solution item context menu
//Deliver
//Rebase
//ClearCase search Context Menus
//System #endregion
#endregion
//------------------------------Code Window------------------------------------------------------
object[] contextUIGuids = new object[] { };
Commands2 commands = (Commands2)_applicationObject.Commands;
try
{
findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_CodeWindow), -);
}
catch
{
// command doesn't exist
} if (findCommand == null)
{
findCommand = commands.AddNamedCommand2(
_addInInstance,
MY_COMMAND_CodeWindow,
MY_COMMAND_CodeWindow,
MY_COMMAND_CodeWindow,
false,
MyVisualStudioAddin.Properties.Resources._default,
ref contextUIGuids,
(int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));
} CommandBars cmdBars = (CommandBars)_applicationObject.CommandBars; if (findCommand != null)
{
// Add a button to the code window context window
//代码
CommandBar codeWindowCommandBar = cmdBars["Code Window"];
//Project
//Solution Folder
if (codeWindowCommandBar != null)
{
findCommandBarButtonButton = (CommandBarButton)findCommand.AddControl(
codeWindowCommandBar, codeWindowCommandBar.Controls.Count + );
findCommandBarButtonButton.Caption = "Code Window";
}
} //-------------------------------------project---------------------------------------------------------------
findCommand = null;
contextUIGuids = new object[] { };
try
{
findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_Project), -);
}
catch
{
// command doesn't exist
} if (findCommand == null)
{
findCommand = commands.AddNamedCommand2(
_addInInstance,
MY_COMMAND_Project,
MY_COMMAND_Project,
MY_COMMAND_Project,
false,
MyVisualStudioAddin.Properties.Resources.man,
ref contextUIGuids,
(int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));
}
if (findCommand != null)
{
//项目
CommandBar codeWindowCommandBar2 = cmdBars["Project"];
//Solution Folder
if (codeWindowCommandBar2 != null)
{
findCommandBarButtonButton = (CommandBarButton)findCommand.AddControl(
codeWindowCommandBar2, codeWindowCommandBar2.Controls.Count + );
findCommandBarButtonButton.Caption = "生成表结构类";
}
}
//-----------------------------------------解决方案---------------------------------------------------------
findCommand = null;
contextUIGuids = new object[] { };
try
{
findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_Solution), -);
}
catch
{
// command doesn't exist
} if (findCommand == null)
{
findCommand = commands.AddNamedCommand2(
_addInInstance,
MY_COMMAND_Solution,
MY_COMMAND_Solution,
MY_COMMAND_Solution,
false,
MyVisualStudioAddin.Properties.Resources.FindHS,
ref contextUIGuids,
(int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));
}
if (findCommand != null)
{
//解决方案
CommandBar codeWindowCommandBar3 = cmdBars["Solution"];
if (codeWindowCommandBar3 != null)
{
findCommandBarButtonButton = (CommandBarButton)findCommand.AddControl(
codeWindowCommandBar3, codeWindowCommandBar3.Controls.Count + );
findCommandBarButtonButton.Caption = "生成表结构类";
}
}
//-------------------------------------------MenuBar-------------------------------------------------------
findCommand = null;
contextUIGuids = new object[] { };
try
{
findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_MenuBar), -);
}
catch
{
// command doesn't exist
} if (findCommand == null)
{
findCommand = commands.AddNamedCommand2(
_addInInstance,
MY_COMMAND_MenuBar,
MY_COMMAND_MenuBar,
MY_COMMAND_MenuBar,
false,
MyVisualStudioAddin.Properties.Resources.man,
ref contextUIGuids,
(int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));
}
if (findCommand != null)
{
//menubar
CommandBar codeWindowCommandBar4 = cmdBars["MenuBar"];
if (codeWindowCommandBar4 != null)
{
findCommandBarButtonButton = (CommandBarButton)findCommand.AddControl(
codeWindowCommandBar4, codeWindowCommandBar4.Controls.Count + );
findCommandBarButtonButton.Caption = "JackWang";
} }
//--------------------------Files------------------------------
findCommand = null;
contextUIGuids = new object[] { };
try
{
findCommand = commands.Item(string.Format("{0}.{1}", _addInInstance.ProgID, MY_COMMAND_Files), -);
}
catch
{
// command doesn't exist
} if (findCommand == null)
{
findCommand = commands.AddNamedCommand2(
_addInInstance,
MY_COMMAND_Files,
MY_COMMAND_Files,
MY_COMMAND_Files,
false,
MyVisualStudioAddin.Properties.Resources.man,
ref contextUIGuids,
(int)(vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled));
}
if (findCommand != null)
{
//menubar
CommandBar codeWindowCommandBar4 = cmdBars["Item"];
if (codeWindowCommandBar4 != null)
{
findCommandBarButtonButton = (CommandBarButton)findCommand.AddControl(
codeWindowCommandBar4, codeWindowCommandBar4.Controls.Count + );
findCommandBarButtonButton.Caption = "生成表结构类";
} } }
         public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText)
{
try
{
if (neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
{
if (commandName == "MyVisualStudioAddin.Connect.MyVisualStudioAddin")
{
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
} if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_FindInSolutionExplorer))
{
Solution solution = _applicationObject.Solution;
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
}
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_CodeWindow))
{
Solution solution = _applicationObject.Solution;
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
}
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_MenuBar))
{
Solution solution = _applicationObject.Solution;
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
}
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Project))
{
Solution solution = _applicationObject.Solution;
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
}
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Solution))
{
Solution solution = _applicationObject.Solution;
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
}
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Files))
{
Solution solution = _applicationObject.Solution;
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
}
}
}
catch (Exception ex)
{
logger.LogError(ex.ToString());
}
}
         public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
{
try
{
handled = false;
if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
{
//命名空间.Connect.命名
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_FindInSolutionExplorer))
{
FindCurrentActiveDocumentInSolutionExplorer();
handled = true;
return;
}
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_CodeWindow))
{
string fullpath = this.GetActiveProjectFullPath();
if (fullpath != "")
{
POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);
frm.Show();
}
handled = true;
return;
}
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_MenuBar))
{
string fullpath = this.GetActiveProjectFullPath();
if (fullpath != "")
{
POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);
frm.Show();
}
handled = true;
return;
}
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Project))
{
string fullpath = this.GetActiveProjectFullPath();
if (fullpath != "")
{
POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);
frm.Show();
} handled = true;
return;
}
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Solution))
{
string fullpath = this.GetActiveProjectFullPath();
if (fullpath != "")
{
POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);
frm.Show();
}
handled = true;
return;
}
if (commandName == string.Format("MyVisualStudioAddin.Connect.{0}", MY_COMMAND_Files))
{
string fullpath = this.GetActiveProjectFullPath();
if (fullpath != "")
{
POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);
frm.Show();
}
handled = true;
return;
} if (commandName == "MyVisualStudioAddin.Connect.MyVisualStudioAddin")
{
string fullpath = this.GetActiveProjectFullPath();
if (fullpath != "")
{
POCOGenerator.ConnectionForm frm = new POCOGenerator.ConnectionForm(fullpath);
frm.Show();
}
handled = true;
return;
} }
}
catch (Exception ex)
{
logger.LogError(ex.ToString());
} }

View Exec Code

  获取当前IDE激活项目的路径:

        /// <summary>
/// Gets the Active project FullPath
/// </summary>
/// <returns></returns>
public string GetActiveProjectFullPath()
{
// Returns the name of the currently selected project in the solution.
Project proj = getActiveProject();
if (proj!=null)
{
string fullPath = proj.Properties.Item("FullPath").Value.ToString();
return fullPath;
// return proj.FullName;
}
return ""; }
/// <summary>
/// Gets the Active project
/// </summary>
/// <returns></returns>
public Project getActiveProject()
{
Array projects = (Array)_applicationObject.ActiveSolutionProjects;
if (projects != null && projects.Length > )
{
return projects.GetValue() as Project;
}
projects = (Array)_applicationObject.Solution.SolutionBuild.StartupProjects;
if (projects != null && projects.Length >= )
{
return projects.GetValue() as Project;
}
projects = (Array)_applicationObject.Solution.Projects;
if (projects != null && projects.Length > )
{
return projects.GetValue() as Project;
}
return null;
}

  关于如何根据数据库结构生成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 Studio中开发自己的代码生成器插件

  如果发布没有错误,那么重新启动Visual Studio2012后,在项目文件上右击弹出菜单,可以看到下面的界面:

如何在Visual Studio中开发自己的代码生成器插件

  同时在菜单栏创建了一个JackWang的命令按钮和工具菜单下还添加了一个MyVS外接程序的命令按钮,如下图:

如何在Visual Studio中开发自己的代码生成器插件

5 代码生成器

  代码生成器(此处用的是yuvalsol的工程,我将其整合到插件中)可以根据用户选择的数据库,选择对应的表,然后生成表结构对应的C#类:

如何在Visual Studio中开发自己的代码生成器插件

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中,卸载完成. 但是要完整去除必须手动删除插件对应的项目文件(如果你再次调试,可能会再次进行注册);

如何在Visual Studio中开发自己的代码生成器插件

7 总结

  通过插件机制可以方便的定制VS IDE, 一般软件公司都有自己的一套框架,其代码也有一定的封装,且各不相同,可以通过扩展VS,通过定制的代码生成工具来快速生成符合本公司所需的代码,从而从重复机械的劳动中解放出来(虽然完全自动生成的代码不可能直接能用,但是人工在此基础上进行调整,也提升了代码的编写效率,而且减少类似于拼写/标点等人为的错误点等.

  虽然我们不生产代码,是代码的搬运工,但是正确的打开方式是用代码去帮我们搬运代码!!!

如何在Visual Studio中开发自己的代码生成器插件