VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发)

这篇具有很好参考价值的文章主要介绍了VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        出于某种目的(合法的,真的合法的,合同上明确指出可以这样做),我准备了一个重命名所有标识符的VS扩展,用来把一个C#库改头换面,在简单的测试项目上工作很满意,所有标识符都被准确替换。我还尝试用在C++项目上,问题就比较多了,因为VS并不能准确识别代码,这说明,C#比C++好用太多了。

        当然,最终合同被放弃了,所以这个东西也没派上用场,纯粹成了我的个人练习(因为没有人指派我做这个程序)。

        本文涉及的代码支持2017、2019和2022,为了稳妥起见,项目本身用不同版本的VS创建,实际代码则放在一个共享文件中,只需要在生成的框架之中加入一句调用代码即可。

目录

一、创建项目框架

1.1 新建VS项目

1.2 添加命令

1.3 测试此框架代码

二、引入实际代码

2.1 添加项目文件

2.2 添加依赖项

三、修改代码

四、测试实际效果

4.1 创建测试项目

4.2 在VSIX项目打开测试项目

4.3 效果

五、代码


        

一、创建项目框架

1.1 新建VS项目

        以下均以VS2022社区版为例。

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        项目类型过滤选择“扩展”,项目类型为“VSIX Project”。

        如果找不到这个,是因为安装的时候没有装,打开安装程序增加选项即可。

        在开始菜单里面找到“Visual Studio Installer”,修改安装选项:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

1.2 添加命令

        创建以后在项目上右键,“添加”-“新建项”:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        “Command”就是一个菜单命令,会出现在VS的“工具”菜单下面。

        添加之后会看到增加了一个文件:Command1.cs,当然如果你改了命令名就是另外一个文件。

        文件不长,直接拉到最后,看最后一个方法的代码:

		/// <summary>
		/// This function is the callback used to execute the command when the menu item is clicked.
		/// See the constructor to see how the menu item is associated with this function using
		/// OleMenuCommandService service and MenuCommand class.
		/// </summary>
		/// <param name="sender">Event sender.</param>
		/// <param name="e">Event args.</param>
		private void Execute(object sender, EventArgs e)
		{
			ThreadHelper.ThrowIfNotOnUIThread();
			string message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.GetType().FullName);
			string title = "Command1";

			// Show a message box to prove we were here
			VsShellUtilities.ShowMessageBox(
				this.package,
				message,
				title,
				OLEMSGICON.OLEMSGICON_INFO,
				OLEMSGBUTTON.OLEMSGBUTTON_OK,
				OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
		}

        好简单的,猜也能猜到就是显示一个消息框。

1.3 测试此框架代码

        编译项目,应该没什么问题(全是开发工具生成的代码嘛)。

        调试或者直接运行不调试(“调试菜单”的“开始执行(不调试)”),会打开一个新的VS2022窗口,像普通VS一样,但是已经加载了扩展。

        选择项目,或者不选择项目直接进入。不选择项目直接进入(点击“继续但无需代码”):

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        工具菜单下会出现“Invoke Command1”(图中还有另外一个相似菜单,是我的正式项目创建的),点击出现:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        这个框架就算完成了,剩下的就是修改命令代码。

二、引入实际代码

2.1 添加项目文件

        在项目上右键,“添加”-“现有项”,找到实际代码文件添加进来,当然你也可以直接放在项目里面,但是因为VS扩展项目是依赖VS版本的,最好把通用部分独立出来。

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        这个位置是在项目之外的,可以由多个项目共享。

2.2 添加依赖项

        文件加进来之后不能编译:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        这是因为缺少依赖项,在“项目”-“引用”上右键,“添加引用”:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        在“程序集”-“扩展”里面找到“Microsoft.VisualStudio.VCCodeModel”,选中,确定。

        然后程序就可以编译了。这个依赖项其实只和C++项目功能有关,删除C++项目相关代码也可以不要这个依赖项。

        如果发生奇怪错误:

严重性	代码	说明	项目	文件	行	禁止显示状态
错误		CreatePkgDef : error : ArgumentException: No Visual Studio registration attribute found in this assembly.
The assembly should contain an instance of the attribute 'Microsoft.VisualStudio.Shell.RegistrationAttribute' defined in assembly 'Microsoft.VisualStudio.Shell.Framework' version '17.0.0.0' 
   在 Microsoft.VisualStudio.Tools.CreatePkgDef.ProcessAssembly(String fileName, Hive hive, PkgDefContext context, Boolean register, RegistrationMode mode) 位置 D:\a\_work\1\s\src\product\vssdk\tools\CreatePkgDef\CreatePkgDef.cs:行号 383
   在 Microsoft.VisualStudio.Tools.CreatePkgDef.DoCreatePkgDef(InputArguments inputArguments) 位置 D:\a\_work\1\s\src\product\vssdk\tools\CreatePkgDef\CreatePkgDef.cs:行号 202
   在 Microsoft.VisualStudio.Tools.CreatePkgDef.Main(String[] arguments) 位置 D:\a\_work\1\s\src\product\vssdk\tools\CreatePkgDef\CreatePkgDef.cs:行号 91	VSIXProject1			

        不要尝试任何解决方案,删除刚才添加的东西也没用,整个过程删掉重来。这可能是VS的BUG。

三、修改代码

        现在我们可以将代码引入,在Command1.cs里面添加如下内容:

//文件头添加对共享代码的引用
using VSIXProjectShare;
using Task = System.Threading.Tasks.Task;

//在类里面添加变量,就近放在构造函数前面好了
		private CommandShare commandshare;

//构造函数最后加上这一句
			commandshare = new CommandShare(this.package);


//Execute最后加一句
			commandshare.Execute();

        最终的Command1.cs是这样的(四处修改在里面已经注明):

using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System;
using System.ComponentModel.Design;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using VSIXProjectShare;//第一处修改
using Task = System.Threading.Tasks.Task;

namespace VSIXProject1
{
	/// <summary>
	/// Command handler
	/// </summary>
	internal sealed class Command1
	{
		/// <summary>
		/// Command ID.
		/// </summary>
		public const int CommandId = 0x0100;

		/// <summary>
		/// Command menu group (command set GUID).
		/// </summary>
		public static readonly Guid CommandSet = new Guid("16dcb30d-2f74-4781-bde4-c21c60716ac8");

		/// <summary>
		/// VS Package that provides this command, not null.
		/// </summary>
		private readonly AsyncPackage package;

		private CommandShare commandshare;//第二处修改

		/// <summary>
		/// Initializes a new instance of the <see cref="Command1"/> class.
		/// Adds our command handlers for menu (commands must exist in the command table file)
		/// </summary>
		/// <param name="package">Owner package, not null.</param>
		/// <param name="commandService">Command service to add command to, not null.</param>
		private Command1(AsyncPackage package, OleMenuCommandService commandService)
		{
			this.package = package ?? throw new ArgumentNullException(nameof(package));
			commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));

			var menuCommandID = new CommandID(CommandSet, CommandId);
			var menuItem = new MenuCommand(this.Execute, menuCommandID);
			commandService.AddCommand(menuItem);

			commandshare = new CommandShare(this.package);//第三处修改
		}

		/// <summary>
		/// Gets the instance of the command.
		/// </summary>
		public static Command1 Instance
		{
			get;
			private set;
		}

		/// <summary>
		/// Gets the service provider from the owner package.
		/// </summary>
		private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
		{
			get
			{
				return this.package;
			}
		}

		/// <summary>
		/// Initializes the singleton instance of the command.
		/// </summary>
		/// <param name="package">Owner package, not null.</param>
		public static async Task InitializeAsync(AsyncPackage package)
		{
			// Switch to the main thread - the call to AddCommand in Command1's constructor requires
			// the UI thread.
			await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);

			OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
			Instance = new Command1(package, commandService);
		}

		/// <summary>
		/// This function is the callback used to execute the command when the menu item is clicked.
		/// See the constructor to see how the menu item is associated with this function using
		/// OleMenuCommandService service and MenuCommand class.
		/// </summary>
		/// <param name="sender">Event sender.</param>
		/// <param name="e">Event args.</param>
		private void Execute(object sender, EventArgs e)
		{
			ThreadHelper.ThrowIfNotOnUIThread();
			string message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.GetType().FullName);
			string title = "Command1-d";//修改这里以确认版本

			// Show a message box to prove we were here
			VsShellUtilities.ShowMessageBox(
				this.package,
				message,
				title,
				OLEMSGICON.OLEMSGICON_INFO,
				OLEMSGBUTTON.OLEMSGBUTTON_OK,
				OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
			commandshare.Execute();//第四处修改

		}
	}
}

        然后编译执行(仍然用“继续但无需代码”):

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        看,版本正确,这是一个小技巧,debug发生困惑的时候先确认版本,不要编译失败执行旧版本。

        点击【确定】后又弹出新的消息框:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        这就对了,因为没有打开项目,共享代码需要项目来操作。这说明共享代码也正确进去了。后面就可以测试实际效果,共享代码放在本文最后。

四、测试实际效果

4.1 创建测试项目

        创建一个C#项目,一个对话框好了:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        一个对话框,有个静态文本,窗口初始化设置了一下文本。

4.2 在VSIX项目打开测试项目

        先创建好这个项目,然后回到VSIX项目,调试或运行,在新打开的VS启动时选择新建的这个项目,打开后是和普通VS一样操作的,只不过多了扩展菜单项。

        现在从工具菜单执行我们的命令,运行时会在输出窗口输出内容,最后会得到一个消息框:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        这就表示正确完成,提示信息是共享代码最后的版本,就是日期和时间。

        输出窗口输出如下:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        注意:此时修改的文件还没保存,要点击“全部保存”来保存文件。

        然后我们看看效果如何,现重新编译程序确认测试项目是正常的。

4.3 效果

        看看代码变成了什么样:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

        Form1.Designer.cs就不贴了。

        看看文件比较:

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发),VSIX扩展开发,visual studio,VSIX,批量rename

五、代码

        共享代码在此,文件名CommandShare.cs:

using System;
using System.ComponentModel.Design;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Task = System.Threading.Tasks.Task;

using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.VCCodeModel;
using System.IO;
using Microsoft.Internal.VisualStudio.PlatformUI;


namespace VSIXProjectShare
{
    public sealed class CommandShare
    {
        private readonly AsyncPackage package;

        enum ProjectType { VC,CSharp,OTHER};//项目类型
        ProjectType projectType;
        private Random r ;//随机数
        private string new_name_title;//新名称标题
        private long count = 0;//顺序编号

        public CommandShare(AsyncPackage _package)
        {
            package = _package;

            Log("初始化插件");

            r = new Random();
            new_name_title = "_ASDFGHJKL_" + r.Next().ToString() + "_";
        }

        //显示消息对话框
        private void ShowMessageBox(string title, string message)
        {
            VsShellUtilities.ShowMessageBox(
               package,
               message,
               title,
               OLEMSGICON.OLEMSGICON_INFO,
               OLEMSGBUTTON.OLEMSGBUTTON_OK,
               OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
        }
        //输出日志
        private void Log(string msg)
        {
            Log(0,msg);
        }
        private void Log(int level,string msg)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            IVsOutputWindowPane pane = (IVsOutputWindowPane)Package.GetGlobalService(typeof(SVsGeneralOutputWindowPane));
            int tmp = pane.Activate();
            if (VSConstants.S_OK != tmp)
            {
                ShowMessageBox("注意", "未能激活输出窗口 " + tmp.ToString());
            }
            for (int i = 0; i < level; ++i)
            {
                pane.OutputStringThreadSafe("    ");
            }
            pane.OutputStringThreadSafe(msg + "\r\n");
        }
        private void AddFunction_myToString(int level, VCCodeElements codeElements)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            IVsOutputWindowPane pane = (IVsOutputWindowPane)Package.GetGlobalService(typeof(SVsGeneralOutputWindowPane));

            string px = new string(' ', level * 4);
            string px2 = new string(' ', 4);
            px = level.ToString() + px;

            string fun_name = "myToString";
            string fun_type = "stringstream &";
            vsCMFunction fun_kind = vsCMFunction.vsCMFunctionFunction | vsCMFunction.vsCMFunctionConstant;

            foreach (VCCodeElement element in codeElements)
            {
                Log(px + "Kind " + element.Kind.ToString() + " Name " + element.Name);
                if (0 != element.Children.Count)
                {
                    AddFunction_myToString(level + 1, element.Children as VCCodeElements);
                }

                if (element.Kind == vsCMElement.vsCMElementClass || element.Kind == vsCMElement.vsCMElementStruct)
                {
                    VCCodeElement Found = null;
                    string bodytext = "";

                    //基类必须首先处理
                    foreach (VCCodeElement chileren in element.Children)
                    {
                        if (chileren.Kind == vsCMElement.vsCMElementVCBase)
                        {
                            Log(px + px2 + "基类 " + chileren.Name);
                            bodytext += "\t\t " + chileren.Name + "::myToString(ss) << \" \";\r\n";
                        }
                    }
                    foreach (VCCodeElement chileren in element.Children)
                    {
                        Log(px + px2 + chileren.Name + " Kind " + chileren.Kind);
                        if (chileren.Kind == vsCMElement.vsCMElementVariable)
                        {
                            VCCodeVariable variable = (VCCodeVariable)chileren;
                            Log(px + px2 + "变量 Name " + variable.Name + " TypeString " + variable.TypeString
                                + " StartPoint " + variable.StartPoint.Line + " " + variable.StartPoint.LineCharOffset
                                + " EndPoint " + variable.EndPoint.Line + " " + variable.EndPoint.LineCharOffset);
                            if (variable.TypeString.EndsWith(")"))
                            {
                                bodytext += "\t\t ss << \"函数指针 " + variable.Name + " \" << " + variable.Name + " << \" \";\r\n";
                            }
                            else if (variable.TypeString.EndsWith("]"))
                            {
                                bodytext += "\t\t ss << \"数组 " + variable.Name + " \" << " + variable.Name + " << \" \";\r\n";
                            }
                            else
                            {
                                bodytext += "\t\t Template_" + fun_name + "(" + variable.Name + ", ss) << \" \";\r\n";
                            }
                        }
                        else if (chileren.Kind == vsCMElement.vsCMElementFunction)
                        {
                            if (chileren.Name == fun_name)
                            {
                                Found = chileren;
                                Log(px + px2 + fun_name + " 已存在,重新创建");
                            }
                        }
                    }

                    VCCodeFunction codeFunction;
                    if (element.Kind == vsCMElement.vsCMElementClass)
                    {
                        VCCodeClass codeClass = (VCCodeClass)element;
                        codeClass.RemoveMember(Found);
                        codeFunction = (VCCodeFunction)codeClass.AddFunction(fun_name, fun_kind, fun_type, -1, vsCMAccess.vsCMAccessPublic);
                    }
                    else
                    {
                        VCCodeStruct codeClass = (VCCodeStruct)element;
                        codeClass.RemoveMember(Found);
                        codeFunction = (VCCodeFunction)codeClass.AddFunction(fun_name, fun_kind, fun_type, -1, vsCMAccess.vsCMAccessPublic);
                    }
                    codeFunction.AddParameter("ss", "stringstream &");
                    codeFunction.Comment = "自动生成的代码";

                    bodytext += "\t\t return ss;";
                    codeFunction.BodyText = bodytext;
                }
            }
        }
        private void CSharp_Rename(int level, CodeElements codeElements)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            foreach (CodeElement _element in codeElements)
            {
                Log(level, "Kind " + _element.Kind.ToString());

                string name = "未知";//Name属性不是每个都有
                if (_element.Kind == vsCMElement.vsCMElementImportStmt)
                {
                    name = "vsCMElementImportStmt";
                }
                else
                {
                    name = _element.Name;//这个竟然不是每个都支持
                }

                CodeElement2 element = (CodeElement2)_element;
                Log(level, "Kind " + element.Kind.ToString() + " Name " + name + " type " + element.GetType().ToString());

                //处理子项
                if (0 != element.Children.Count)
                {
                    CSharp_Rename(level + 1, element.Children);
                }

                bool skip = false;//是否需要跳过
                
                //检查是否已经处理过
                if (name.StartsWith(new_name_title))
                {
                    skip = true;
                }

                if (element.Kind == vsCMElement.vsCMElementVariable)
                {
                    CodeVariable variable = (CodeVariable)element;
                    Log(level + 1, "变量 Name " + variable.Name
                        + " StartPoint " + variable.StartPoint.Line + " " + variable.StartPoint.LineCharOffset
                        + " EndPoint " + variable.EndPoint.Line + " " + variable.EndPoint.LineCharOffset);
                }
                else if (element.Kind == vsCMElement.vsCMElementFunction)
                {
                    Log(level + 1, "函数 " + name);
                    if (name.Equals("Main"))
                    {
                        Log(level + 1, "Main函数(跳过) " + name);
                        skip = true;
                    }
                    if (name.Equals("Dispose"))
                    {
                        Log(level + 1, "Dispose函数(跳过) " + name);
                        skip = true;
                    }
                }
                else if (element.Kind == vsCMElement.vsCMElementNamespace)
                {
                    Log(level + 1, "命名空间 " + name);
                    //skip = true;
                }
                else if (element.Kind == vsCMElement.vsCMElementAttribute)
                {
                    Log(level + 1, "属性(跳过) " + name);
                    skip = true;
                }
                else if (element.Kind == vsCMElement.vsCMElementImportStmt)
                {
                    Log(level + 1, "导入语句(跳过) " + name);
                    skip = true;
                }
                else if (element.Kind == vsCMElement.vsCMElementOther)
                {
                    Log(level + 1, "vsCMElementOther(跳过) " + name);
                    skip = true;
                }
                

                if (!skip)
                {
                    Log(level, "重命名 " + name + "(" + element.Kind.ToString() + ") 为 " + new_name_title + count.ToString());
                    element.RenameSymbol(new_name_title + count.ToString());
                    count++;
                    Log(level, "重命名完成");
                }
            }
        }
        private void ProcessProjectItem(int level, ProjectItem projectItem)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            //项目下的筛选器
            Log(level, "===============目录:" + projectItem.Name + " 项目子项FileCount:" + projectItem.FileCount.ToString());
            for (short i = 0; i < projectItem.FileCount; i++)
            {
                Log(3, "文件名:" + projectItem.FileNames[i]);
            }
            if (projectType == ProjectType.CSharp && projectItem.Name == "Properties")
            {
                Log(3, "C#项目忽略属性目录");
                return;
            }
            if (null != projectItem.FileCodeModel)
            {
                String language = "未知语言";
                switch (projectItem.FileCodeModel.Language)
                {
                    case CodeModelLanguageConstants.vsCMLanguageVC:
                        language = "VC";
                        AddFunction_myToString(5, projectItem.FileCodeModel.CodeElements as VCCodeElements);
                        break;
                    case CodeModelLanguageConstants.vsCMLanguageIDL:
                        language = "IDL";
                        Log(3, "未支持的语言 " + language);
                        break;
                    case CodeModelLanguageConstants.vsCMLanguageVB:
                        language = "VB";
                        Log(3, "未支持的语言 " + language);
                        break;
                    case CodeModelLanguageConstants.vsCMLanguageMC:
                        language = "MC";
                        Log(3, "未支持的语言 " + language);
                        break;
                    case CodeModelLanguageConstants.vsCMLanguageCSharp:
                        language = "CSharp";
                        Log(3, "语言 " + language);
                        if (null == projectItem) Log(3, "语言1" + language);
                        if (null == projectItem.FileCodeModel) Log(3, "语言 2" + language);
                        if (null == projectItem.FileCodeModel.CodeElements) Log(3, "语言 3" + language);
                        Log(3, "语言 " + language);
                        CSharp_Rename(5, projectItem.FileCodeModel.CodeElements);
                        break;
                }

            }
            foreach (ProjectItem current_project_item_item in projectItem.ProjectItems)
            {
                ProcessProjectItem(level + 1, current_project_item_item);
            }
        }

        public void Execute()
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            string message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.GetType().FullName);
            string title = "Command1 2023-04-20 1720";

            // Show a message box to prove we were here
            //VsShellUtilities.ShowMessageBox(
            //    this.package,
            //    message,
            //    title,
            //    OLEMSGICON.OLEMSGICON_INFO,
            //    OLEMSGBUTTON.OLEMSGBUTTON_OK,
            //    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
            Log(title);

            try
            {
                DTE2 dte = (DTE2)Package.GetGlobalService(typeof(SDTE));
                Log("DTE:" + dte.Version);
                Log("DTE:" + dte.Name);
                Log("DTE:" + dte.Edition);
                Log("DTE:" + dte.Mode);

                var solution = dte.Solution;
                var SolutionName = Path.GetFileName(solution.FullName);     //解决方案名称
                var SolutionPath = Path.GetDirectoryName(solution.FullName);//解决方案路径
                Log("解决方案:" + solution.ToString());
                Log("解决方案FileName:" + solution.FileName);
                Log("解决方案FullName:" + solution.FullName);
                Log("解决方案GetFileName:" + SolutionName);
                Log("解决方案GetDirectoryName:" + SolutionPath);
                Log("解决方案Count:" + solution.Count);
                Log("解决方案Projects.Count:" + solution.Projects.Count);

                foreach (Project current_project in solution.Projects)
                {
                    //解决方案下的项目
                    Log(1, "--------------------------Language:" + current_project.CodeModel.Language);
                    if (current_project.CodeModel.Language == "{B5E9BD34-6D3E-4B5D-925E-8A43B79820B4}")
                    {
                        projectType = ProjectType.CSharp;
                    }
                    else if (current_project.CodeModel.Language == "{B5E9BD32-6D3E-4B5D-925E-8A43B79820B4}")
                    {
                        projectType = ProjectType.VC;
                    }
                    else
                    {
                        projectType = ProjectType.OTHER;
                    }
                    Log(1, "--------------------------项目:" + current_project.Name + " 类型 " + projectType + " 项目子项个数:" + current_project.ProjectItems.Count.ToString());

                    foreach (ProjectItem current_project_item in current_project.ProjectItems)
                    {
                        ProcessProjectItem(2, current_project_item);
                    }
                }

                ShowMessageBox(title, "操作完成");
            }
            catch (Exception ex)
            {
                ShowMessageBox("", ex.Message);
            }
        }
    }
}

        这个代码对C#项目执行CSharp_Rename,对C++项目则执行AddFunction_myToString,功能是给所有结构添加toString函数,尚不完善,所以无视即可(其实我最开始折腾VSIX就是为了写这个功能的,我挺希望别人能把这个功能做出来)。

        代码分析看这里:VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发)代码详解-CSDN博客。

(这里是结束)文章来源地址https://www.toymoban.com/news/detail-743866.html

到了这里,关于VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言趣味教程】(4) 变量:代码注释 | 变量的声明 | 初始化与赋值 | 变量的命名 | 关键字 | 标识符 | 变量名的命名规范

      🔗 《C语言趣味教程》👈 猛戳订阅!!! 0x00 引入:注释的作用 \\\"程序员最讨厌两种人:一种是不写注释的人,一种是让我写注释的人。\\\" 相信大家对注释早已有所耳闻,对于注释,C 语言有两种注释风格,我们下面会逐个讲解。   但在这之前,我们先来了解了解注释的作

    2024年02月15日
    浏览(48)
  • [HTML]Web前端开发技术25(HTML5、CSS3、JavaScript )JavaScript基础消息对话框告警框确认框提示框命名规范1标识符2关键字3保留字注释标识符和变量——喵喵画网页

    希望你开心,希望你健康,希望你幸福,希望你点赞! 最后的最后,关注喵,关注喵,关注喵,佬佬会看到更多有趣的博客哦!!! 喵喵喵,你对我真的很重要! 目录 前言 JavaScript程序 代码 消息对话框 消息对话框-告警框 消息对话框-确认框 消息对话框-提示框 JavaScript注释

    2024年02月20日
    浏览(55)
  • 错误C2065:未声明的标识符 - 解决C++中的未声明标识符错误

    错误C2065:未声明的标识符 - 解决C++中的未声明标识符错误 在C++编程中,错误C2065是一种常见的编译错误,它表示使用了一个未声明的标识符。通常情况下,这个错误是由于忘记包含必要的头文件或者拼写错误导致的。本文将介绍如何解决这个错误,并提供相应的源代码示例

    2024年02月06日
    浏览(49)
  • 初识标识符

    abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implementis import instanceof int interface long native new package private protected public return strictfp short static super switch synchronized this throw throws transient try void volatile while   java所有的组成

    2024年02月11日
    浏览(59)
  • go学习-指针 标识符

    1.指针 (1).基本介绍 1)基本数据类型,变量存的值,也叫值类型 2)获取变量的地址用,比如 var num int ,获取num的地址:num 3)指针类型,变量存的是一个地址,这个地址指向的空间存的才是真正值,比如: var ptr *int =num 4)获取指针类型所指的值,使用*,比如:var *ptr int,使用

    2024年02月11日
    浏览(49)
  • 解决C++遇到的未定义标识符 “string“、未定义标识符 “cout“、“name”: 未知重写说明符错误

    目录 解决C++遇到的未定义标识符 \\\"string\\\"、未定义标识符 \\\"cout\\\"、“name”: 未知重写说明符错误 1. 未定义标识符 \\\"string\\\" 2. 未定义标识符 \\\"cout\\\" 3. “name”: 未知重写说明符错误 总结 1. 未定义标识符 \\\"string\\\" 2. 未定义标识符 \\\"cout\\\" 3. “name”: 未知重写说明符错误 在C++编程中,我们可

    2024年02月06日
    浏览(96)
  • 第6关:Python的标识符

    2023年04月09日
    浏览(45)
  • 电脑的唯一标识符,VC++如何读出?

    电脑有没有唯一标识符,查了一些资料,开始以为CPUID可以,但是实际上统一类型的CPU用的是相同的ID: 那么BIOS ID是否是唯一的呢?主板上 的BIOS 芯片是主板上 唯一 贴有标签的芯片,如果电脑开机时登录bios可以看到里面的一些基本信息: bios编号也可以用win cmd的命令获得,

    2024年02月12日
    浏览(55)
  • Android设备的各种唯一标识符 ID

    只有Android手机才有, IMEI号是一串15位的号码,比如像这样 359881030314356 需要权限 android.permission.READ_PHONE_STATE 通常用户会因为你向他们要了这个权限而给你一个差评,因为他们觉得你就是在窃取他们的隐私,很明显,你就是在收集一些数据 这个是不靠谱的,因为有时候它是

    2024年02月11日
    浏览(60)
  • ora-12154无法解析指定的连接标识符

    用户反映查询的时候报错ora-12154 这个系统只做历史数据查询使用,使用并不平凡,该数据库曾做过一次服务器间的迁移。 用户描述,所有oracle客户端查询该视图都报tns错误,一般ora-12154会发生在连接数据库时,因为tns配置不正确而报错,但是这个报错发生在进行查询过程中

    2024年01月23日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包