经营性质的网站,在哪里申请网站,网站模板种类,wordpress伪装成破解成功出于某种目的#xff08;合法的#xff0c;真的合法的#xff0c;合同上明确指出可以这样做#xff09;#xff0c;我准备了一个重命名所有标识符的VS扩展#xff0c;用来把一个C#库改头换面#xff0c;在简单的测试项目上工作很满意#xff0c;所有标识符都被准确替换… 出于某种目的合法的真的合法的合同上明确指出可以这样做我准备了一个重命名所有标识符的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 Project”。
1.2 添加命令 创建以后在项目上右键“添加”-“新建项” “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 namesenderEvent sender./param/// param nameeEvent args./paramprivate 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 hereVsShellUtilities.ShowMessageBox(this.package,message,title,OLEMSGICON.OLEMSGICON_INFO,OLEMSGBUTTON.OLEMSGBUTTON_OK,OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);}好简单的猜也能猜到就是显式一个消息框。
1.3 测试此框架代码 编译项目应该没什么问题全是开发工具生成的代码嘛。 调试或者直接运行不调试“调试菜单”的“开始执行不调试”会打开一个新的VS2022窗口像普通VS一样但是已经加载了扩展。 选择项目或者不选择项目直接进入。不选择项目直接进入点击“继续但无需代码” 工具菜单下会出现“Invoke Command1”图中还有另外一个相似菜单是我的正式项目创建的点击出现 这框架就算完成了剩下的就是修改命令代码。
二、引入实际代码
2.1 添加项目文件 在项目上右键“添加”-“现有项”找到实际代码文件添加进来当然你也可以直接放在项目里面但是因为VS扩展项目是依赖VS版本的最好把通用部分独立出来。 这个位置是在项目之外的可以由多个项目共享。
2.2 添加依赖项 文件加进来之后不能编译 因为缺少依赖项在“项目”-“引用”上右键“添加引用” 在“程序集”-“扩展”里面找到“Microsoft.VisualStudio.VCCodeModel”选中确定。 然后程序就可以编译了。这个依赖项其实只和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/// /summaryinternal sealed class Command1{/// summary/// Command ID./// /summarypublic const int CommandId 0x0100;/// summary/// Command menu group (command set GUID)./// /summarypublic static readonly Guid CommandSet new Guid(16dcb30d-2f74-4781-bde4-c21c60716ac8);/// summary/// VS Package that provides this command, not null./// /summaryprivate readonly AsyncPackage package;private CommandShare commandshare;//第二处修改/// summary/// Initializes a new instance of the see crefCommand1/ class./// Adds our command handlers for menu (commands must exist in the command table file)/// /summary/// param namepackageOwner package, not null./param/// param namecommandServiceCommand service to add command to, not null./paramprivate 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./// /summarypublic static Command1 Instance{get;private set;}/// summary/// Gets the service provider from the owner package./// /summaryprivate Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider{get{return this.package;}}/// summary/// Initializes the singleton instance of the command./// /summary/// param namepackageOwner package, not null./parampublic static async Task InitializeAsync(AsyncPackage package){// Switch to the main thread - the call to AddCommand in Command1s 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 namesenderEvent sender./param/// param nameeEvent args./paramprivate 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 hereVsShellUtilities.ShowMessageBox(this.package,message,title,OLEMSGICON.OLEMSGICON_INFO,OLEMSGBUTTON.OLEMSGBUTTON_OK,OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);commandshare.Execute();//第四处修改}}
}然后编译执行仍然用“继续但无需代码” 看版本正确这是一个小技巧debug发生困惑的时候先确认版本不要编译失败执行旧版本。 这就对了因为共享代码需要项目来操作。这说明共享代码也正确进去了。后面就可以测试实际效果共享代码放在本文最后。
四、测试实际效果
4.1 创建测试项目 创建一个C#项目一个对话框好了 一个对话框有个静态文本窗口初始化设置了一下文本。
4.2 在VSIX项目打开测试项目 先创建好这个项目然后回到VSIX项目调试或运行在新打开的VS启动时选择新建的这个项目打开后是和普通VS一样操作的只不过多了扩展菜单项。 现在从工具菜单执行我们的命令运行时会在输出窗口输出内容最后会得到一个消息框 这就表示正确完成提示信息是共享代码最后的版本就是日期和时间。 输出窗口输出如下 注意此时修改的文件还没保存要点击“全部保存”来保存文件。 然后我们看看效果如何现重新编译程序确认测试项目是正常的。
4.3 效果 看看代码变成了什么样 Form1.Designer.cs就不贴了。 看看文件比较 五、代码 共享代码在此文件名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函数尚不完善所以无视即可我挺希望别人能把这个功能做出来。 代码分析看这里VSIXC#项目 重命名所有标识符Visual Studio扩展开发代码详解-CSDN博客。 这里是结束