在上一個項目中由于修改代碼 裡面的添加/删除/修改的注釋都有規範,是以做了一個注釋的第三方dll小插件。效果不錯,被日本Nes要去全面推廣讓其他協力公司都用。
是以提取出來發給大家。先上代碼。在Vs2012裡面。我試了下沒成功,是以先發代碼。稍後我整合打包傳上來了。
VS 建立外接程式 參考連結
http://technet.microsoft.com/zh-tw/library/90855k9f
http://technet.microsoft.com/zh-cn/library/ms165621
http://technet.microsoft.com/zh-cn/library/7k3w6w59
http://www.cnblogs.com/Reborn/archive/2010/02/04/1664010.html C#利用外接程式生成解決方案
http://technet.microsoft.com/zh-cn/magazine/ms228771%28VS.90%29.aspx 如何:在外接程式按鈕上顯示自定義圖示
Connect.cs 最重要的類。注釋的方法都在裡面
/// <summary>用于實作外接程式的對象。</summary>
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
{
// 添加在菜單欄裡面
// CommandBar.resx.
ResourceManager resourceManager = new ResourceManager("StarkingCommentTool.CommandBar", Assembly.GetExecutingAssembly());
CultureInfo cultureInfo = new System.Globalization.CultureInfo(_applicationObject.LocaleID);
string resourceName = String.Concat(cultureInfo.TwoLetterISOLanguageName, "Tools");
toolsMenuName = resourceManager.GetString(resourceName);
}
catch
{
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 commandA = commands.AddNamedCommand2(_addInInstance, "Add", "Add", "Add Comment", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
Command commandD = commands.AddNamedCommand2(_addInInstance, "Del", "Del", "Delete Comment", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
Command commandC = commands.AddNamedCommand2(_addInInstance, "Chg", "Chg", "Change Comment", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
//将對應于該指令的控件添加到“工具”菜單:
if ((commandA != null) && (commandD != null) && (commandC != null) && (toolsPopup != null))
{
commandA.AddControl(toolsPopup.CommandBar, 1);
commandD.AddControl(toolsPopup.CommandBar, 1);
commandC.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)
{
ReadConf();
}
/// <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)
{
switch (commandName)
{
case "StarkingCommentTool.Connect.Add":
goto case "StarkingCommentTool.Connect.Chg";
case "StarkingCommentTool.Connect.Del":
goto case "StarkingCommentTool.Connect.Chg";
case "StarkingCommentTool.Connect.Chg":
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
}
}
}
private DTE2 _applicationObject;
private AddIn _addInInstance;
private string _add1 = "";//before add
private string _add2 = "";//after add
private string _del1 = "";//before del
private string _del2 = "";//after del
private string _changeBefore1 = "";//change before
private string _changeAfter2 = "";//change after
private string _changeDel = "";// comment ///
private bool _autoCopy = true;//複制
private void ReadConf()
{
try
{
string strPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Visual Studio 2012\Addins\StarkingCommentTool.conf";
string strUserName = Environment.UserName;
string strDateFormat = "yyyy.MM.dd";
string strAddFormatA = "NES Add {0} {1}";
string strAddFormatB = "NES Add {0} {1}";
string strDelFormatA = "NES Del {0} {1}";
string strDelFormatB = "NES Del {0} {1}";
string strCgAFormatB = "NES Change After {0} {1}";
string strCgBFormatA = "NES Change Before {0} {1}";
string strAllA = "";
string strAllB = "";
string strAddA = "";
string strAddB = "";
string strDelA = "";
string strDelB = "";
string strCgAB = "";
string strCgBA = "";
string strComm = "";
if (!File.Exists(strPath))
{
System.Windows.Forms.MessageBox.Show("Starking_comment_tool can't read config file \rplease check it exist!", "Starking_comment_tool Error");
}
else
{
XmlDocument xd = new XmlDocument();
xd.Load(strPath);
XmlNode root = xd.ChildNodes[1];
//取出XML配置檔案裡面的自定義内容
strAddFormatA = root.SelectSingleNode("/config/before/add").InnerText;
strDelFormatA = root.SelectSingleNode("/config/before/del").InnerText;
strCgBFormatA = root.SelectSingleNode("/config/before/changeBefore").InnerText;
strAddFormatB = root.SelectSingleNode("/config/after/add").InnerText;
strDelFormatB = root.SelectSingleNode("/config/after/del").InnerText;
strCgAFormatB = root.SelectSingleNode("/config/after/changeAfter").InnerText;
strComm = root.SelectSingleNode("/config/comment").InnerText + " ";
_changeDel = strComm;
strDateFormat = root.SelectSingleNode("/config/dateFormat").InnerText + " ";
//
//取出XML配置檔案節點other裡面的自定義内容
strAllA = root.SelectSingleNode("/config/other/before/all").InnerText;
strAddA = root.SelectSingleNode("/config/other/before/add").InnerText;
strDelA = root.SelectSingleNode("/config/other/before/del").InnerText;
strCgBA = root.SelectSingleNode("/config/other/before/changeBefore").InnerText;
strAllB = root.SelectSingleNode("/config/other/after/all").InnerText;
strAddB = root.SelectSingleNode("/config/other/after/add").InnerText;
strDelB = root.SelectSingleNode("/config/other/after/del").InnerText;
strCgAB = root.SelectSingleNode("/config/other/after/changeAfter").InnerText;
string strAutoCopy = root.SelectSingleNode("/config/changeAutoCopy").InnerText;
bool.TryParse(strAutoCopy, out _autoCopy);
}
string strDate = DateTime.Now.ToString(strDateFormat);
//add
_add1 = strComm + string.Format(strAddFormatA, strDate, strUserName) + strAddA + strAllA + Environment.NewLine;
_add2 = strComm + string.Format(strAddFormatB, strDate, strUserName) + strAddB + strAllB + Environment.NewLine;
//change
_changeBefore1 = strComm + string.Format(strCgBFormatA, strDate, strUserName) + strCgBA + strAllA + Environment.NewLine;
_changeAfter2 = strComm + string.Format(strCgAFormatB, strDate, strUserName) + strCgAB + strAllB + Environment.NewLine;
//delete
_del1 = strComm + string.Format(strDelFormatA, strDate, strUserName) + strDelA + strAllA + Environment.NewLine;
_del2 = strComm + string.Format(strDelFormatB, strDate, strUserName) + strDelB + strAllB + Environment.NewLine;
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
/// <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)
{
switch (commandName)
{
#region//StarkingCommentTool.Connect.Add
case "StarkingCommentTool.Connect.Add":
TextSelection ts = _applicationObject.ActiveDocument.Selection as TextSelection;
int TopLine = ts.TopPoint.Line;
int ButtomLine = ts.BottomPoint.Line;
bool ButtomAtStartOfLine = ts.BottomPoint.AtStartOfLine;
int startLine = 0;
int endLine = 0;
if (TopLine == ButtomLine)
{
ts.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn, false);
ts.Insert(_add1, 0);
ts.SmartFormat();
ts.LineDown(false, 1);
ts.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn, false);
ts.Insert(_add2, 0);
ts.SmartFormat();
ts.GotoLine(TopLine + 2, false);
}
else
{
if (ts.TopPoint.AtEndOfLine)
{
ts.GotoLine(TopLine + 1, false);
ts.Insert(_add1, 0);
}
else
{
ts.GotoLine(TopLine, false);
ts.Insert(_add1, 0);
}
ts.SmartFormat();
if (ButtomAtStartOfLine)
{
ts.GotoLine(ButtomLine + 1, false);
ts.Insert(_add2, 0);
}
else
{
ts.GotoLine(ButtomLine + 2, false);
ts.Insert(_add2, 0);
}
ts.SmartFormat();
}
handled = true;
return;
#endregion
#region//StarkingCommentTool.Connect.Del
case "StarkingCommentTool.Connect.Del":
ts = _applicationObject.ActiveDocument.Selection as TextSelection;
TopLine = ts.TopPoint.Line;
ButtomLine = ts.BottomPoint.Line;
ButtomAtStartOfLine = ts.BottomPoint.AtStartOfLine;
// Area Delete
if (ts.TopPoint.AtEndOfLine)
{
ts.GotoLine(TopLine + 1, false);
startLine = TopLine + 2;
ts.Insert(_del1, 0);
}
else
{
ts.GotoLine(TopLine, false);
startLine = TopLine + 1;
ts.Insert(_del1, 0);
}
if (ButtomAtStartOfLine)
{
ts.GotoLine(ButtomLine + 1, false);
endLine = ButtomLine;
ts.Insert(_del2, 0);
}
else
{
ts.GotoLine(ButtomLine + 2, false);
endLine = ButtomLine + 1;
ts.Insert(_del2, 0);
}
for (int line = startLine; line < endLine + 1; line++)
{
ts.GotoLine(line, false);
ts.SelectLine();
if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion"))
{
ts.Insert(ts.Text.TrimStart(" ".ToCharArray()), 0);
}
if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion"))
{
ts.Insert(_changeDel + ts.Text.TrimStart(" ".ToCharArray()), 0);
}
}
//縮放注釋到多少列 start==>end
ts.GotoLine(TopLine, false);
//計算選中的行數來進行注釋
if (TopLine == ButtomLine)
{ //單行删除注釋
ts.LineDown(true, ButtomLine + 3 - TopLine);
}
else
{ //多行删除注釋
ts.LineDown(true, ButtomLine + (endLine + 1 - startLine) - TopLine);
}
ts.SmartFormat();
handled = true;
return;
#endregion
#region//StarkingCommentTool.Connect.Chg
case "StarkingCommentTool.Connect.Chg":
ts = _applicationObject.ActiveDocument.Selection as TextSelection;
TopLine = ts.TopPoint.Line;
ButtomLine = ts.BottomPoint.Line;
ButtomAtStartOfLine = ts.BottomPoint.AtStartOfLine;
int intCount = ts.TextRanges.Count;
if (TopLine == ButtomLine)//單行變更
{
ts.GotoLine(TopLine, false);
ts.SelectLine();
//選中要變化的内容
string strText = string.Empty;
if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion"))
{
strText = ts.Text.TrimStart(" ".ToCharArray());
}
if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion"))
{
strText = ts.Text.TrimStart(" ".ToCharArray());
}
string strText2 = _changeBefore1 + _changeDel + strText.Replace(" ", "");
//複制要變更的内容
if (_autoCopy)
strText2 += strText;
else
strText2 += Environment.NewLine;
strText2 += _changeAfter2;
//插入變更内容
ts.Insert(strText2, 0);
ts.GotoLine(TopLine, false);
//單行删除注釋
ts.LineDown(true, ButtomLine + 4 - TopLine);
ts.SmartFormat();
}
else//多行内容變更
{
if (!ts.TopPoint.AtEndOfLine && !ButtomAtStartOfLine)
{
intCount++;
}
if (ts.TopPoint.AtEndOfLine)
{
ts.GotoLine(TopLine + 1, false);
startLine = TopLine + 2;
ts.Insert(_changeBefore1, 0);
}
else
{
ts.GotoLine(TopLine, false);
startLine = TopLine + 1;
ts.Insert(_changeBefore1, 0);
}
if (ButtomAtStartOfLine)
{
ts.GotoLine(ButtomLine + 1, false);
endLine = ButtomLine;
}
else
{
ts.GotoLine(ButtomLine + 2, false);
endLine = ButtomLine + 1;
}
//存放選中變化的内容
StringBuilder sb = new StringBuilder();
if (_autoCopy)
{
for (int line = startLine; line < endLine + 1; line++)
{
ts.GotoLine(line, false);
ts.SelectLine();
sb.Append(ts.Text);
}
}
//循環注釋掉選中的内容
for (int line = startLine; line < endLine + 1; line++)
{
ts.GotoLine(line, false);
ts.SelectLine();
if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion"))
{
ts.Insert(ts.Text.TrimStart(" ".ToCharArray()), 0);
}
if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion"))
{
ts.Insert(_changeDel + ts.Text.TrimStart(" ".ToCharArray()), 0);
}
}
//複制選中的内容到計算好的行數中
ts.GotoLine(endLine + 1, false);
if (_autoCopy)
{
ts.Insert(sb.ToString(), 0);
ts.GotoLine(endLine + intCount, false);
}
else
{
ts.NewLine(1);
}
//插入注釋結束語句
ts.Insert(_changeAfter2, 0);
ts.GotoLine(TopLine, false);
//計算行數光标停止在最後一行+1行
ts.LineDown(true, (endLine + intCount + 1) - TopLine);
ts.SmartFormat();
}
handled = true;
return;
#endregion
}
}
}
}
StarkingCommentTool.AddIn 建立自動産生的裡面放外接程式的資訊
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<Extensibility xmlns="http://schemas.microsoft.com/AutomationExtensibility">
<HostApplication>
<Name>Microsoft Visual Studio</Name>
<Version>11.0</Version>
</HostApplication>
<Addin>
<FriendlyName>StarkingCommentTool</FriendlyName>
<Description>C# VC VB.NET JS 注釋工具</Description>
<Assembly>StarkingCommentTool.dll</Assembly>
<FullClassName>StarkingCommentTool.Connect</FullClassName>
<LoadBehavior>5</LoadBehavior>
<CommandPreload>1</CommandPreload>
<CommandLineSafe>1</CommandLineSafe>
</Addin>
</Extensibility>
StarkingCommentTool.conf 配置檔案 你可以配置成自己想要的注釋風格
<?xml version="1.0" encoding="utf-8" ?>
<config>
<!--
add: 追加
del: 削除
changeAfter: 変更前
changeBefore: 変更後
{0}: 時間格式化
NOTE: 請不要删除此檔案中的注釋(重要都是配置節點)
-->
<before>
<!-- 変更前的應用 -->
<add>{0}1處System對應 INSERT START</add>
<del>{0}1處System對應 DELETE START</del>
<changeBefore>{0}1處System對應 UPDATE START</changeBefore>
</before>
<after>
<!-- 変更後的應用 -->
<add>{0}1處System對應 INSERT END</add>
<del>{0}1處System對應 DELETE END</del>
<changeAfter>{0}1處System對應 UPDATE END</changeAfter>
</after>
<!-- dateFormat:日期格式化
例:
日付 2012年12月25日
dateFormat: yyyy.MM.dd
注釋中的格式為中 2012.12.25 。
-->
<dateFormat>yy/MM/dd</dateFormat>
<other>
<!--
all: 追加,削除,変更前,変更後等最後要追加的文字。
add: 追加後最後要追加的文字。
del: 削除後最後要追加的文字。
changeAfter: 修改前最後要追加的文字。
changeBefore: 修改後変最後要追加的文字。
all的優先級是最低的
例如 other中, 如果添加了all和add的場合, 那麼注釋中就會顯示other.add other.all的樣子。
-->
<before>
<all></all>
<add></add>
<del></del>
<changeBefore></changeBefore>
</before>
<after>
<all></all>
<add></add>
<del></del>
<changeAfter></changeAfter>
</after>
</other>
<!-- 修改的内容是否複制-->
<changeAutoCopy>True</changeAutoCopy>
<!-- 注釋
VB: '
C#: ///
-->
<comment>///</comment>
</config>
先貼出代碼,稍後我整理測試完畢打包上傳。