一个vscode自动attach进程的插件开发实例
最近一段时间,接到一个预研任务。我们的现有系统是QT + C++开发的,现在需要实现一个功能,能让用户在系统运行过程中,随时在UI上打开系统加载的一些C++动态库的源代码,并自动attach到UI的exe进程上进行调试。
经过技术选型,决定使用当前比较火的vscode来实现。vscode简单来说是一个轻量版的visual studio,支持多种语言的开发,而且在其上进行自定义插件开发也很方便,可以很好地满足我的上述需求。vscode插件开发的相关资料网上很少,本人以前从来未接触过这方面的工作内容,也是一步步自己摸索,并根据自己的理解,经过一个多星期的研究,最终初步完成了一个可用的插件。所以决定把研究过程遇到的问题和踩过的坑写下来,供新手参考,独乐乐不如众乐乐。废话不多说,直接上步骤。
一 :安装vscode和c++开发扩展
首先安装vscode,网上很多资料,去官网上下载一个vscode安装包,根据安装向导一步步安装就行。安装完vscode后,需要安装c++的开发扩展,cpptools-win32.vsix。 这个需要打开vscode,在左侧的Extension中安装,可以在 线search extensions搜索该扩展插件,也可以先下载该vsix,选择“Install from VSIX”进行安装。
二 :安装yo和generator-code
这两个工具很多地方都称为“脚手架”,可以理解为一个可以为你搭建插件框架的工具,它能帮你自动生成插件运行需要的一些文件。其中最重要的是package.json文件,该文件用于配置插件的入口、触发事件、contributes等重要信息。
小技巧:本来这两个工具可以通过npm在线安装,但是因为公司不能上外网(遇到这种情况,真是无语的很啊),所以这两个工具不能在线安装。但是也不是完全没办法。一个办法就是在GitHub上下载一份别人写好的vscode插件源码,一般都包含有所有必需的文件,可以在此基础上修改,开发自己的插件
三:package.json文件配置
下面就要开始对这个插件进行配置了,该文件最主要几个配置信息如下:
"main": "./src/extension",
此处配置你的插件入口,一般是一个js文件。(vscode是以node.js作为js的运行环境的)。本例中,插件入口在extension.js文件中。
"contributes": {
"commands": [
{
"command": "Hello",
"title": "Hello,my first plugin"
},
],
"menus": {
"editor/context": [
{
"when": "editorFocus",
"command": "Hello",
"group": "navigation@6"
},
]
},
"keybindings": [
{
"command": "Hello",
"key": "ctrl+f10",
"mac": "cmd+f10",
"when": "editorTextFocus"
},
]
}
此处配置插件的“贡献点”,可以添加命令、菜单项、快捷键等等。本例中我们添加一个测试的命令Hello,在编辑器处于焦点时,右键菜单中添加了一个Hello菜单项,并为其设置一个快捷键Ctrl+F10.
"activationEvents": [
"onLanguage:cpp"
],
此处配置插件的激活事件,支持以下几种事件:
onLanguage:${language}
onCommand:${command}
onDebug
workspaceContains:${toplevelfilename}
onFileSystem:${scheme}
onView:${viewId}
onUri
*
回到我们的需求,我们需要在UI上打开c++源码文件,并自动attach到UI的exe进程上。所以我这里把插件的激活事件配置成“OnLanguage::cpp”,意思是每当在vscode中新打开了一个cpp文件时,就激活插件,进入插件入口文件extension.js,开始执行自己的业务逻辑。(特别说一下的是: *表示的是vscode一启动就激活插件,一般不太推荐,因为这样流程不太好控制)
四:extension.js编写
const vscode = require('vscode'); //加载内置vscode开发包,包含vscode的所有API
//插件被激活时触发的函数
exports.activate = function(context) {
console.log('vscode-myplugin被激活');
require('./hello')(context); // hello命令
require('./autoAttach')(context); // 自动attach业务逻辑(核心业务)
};
// 插件被释放时触发的函数
exports.deactivate = function() {
console.log('vscode-myplugin被释放')
};
可以按业务逻辑,分成多个js文件编写。例如我们可以为每个command写一个js,为每种业务逻辑编写一个js。在activate函数中依次执行这些js文件即可。
以下是Hello命令的hello.js代码:
const vscode = require('vscode');
module.exports = function(context) {
// 注册Hello命令
context.subscriptions.push(vscode.commands. ('Hello', () => {
vscode.window.showInformationMessage('Hello!My first Plugin ');
}));
};
代码比较简单,就是利用vscode.commands的registerCommand这个API注册Hello命令,注意这里注册的命令名称一定要在上面的package.json文件的commands中配置过的,否则会报错。
以下是autoAttach.js文件代码:
const vscode = require('vscode');
var path = require('path'); //处理路径的包
var cp = require('child_process');
module.exports = function(context) {
//获取当前打开的cpp文件绝对路径
var curFileName = vscode.window.activeTextEditor.document.fileName;
console.log('当前打开的文件路径:');
console.log(curFileName);
//获取当前cpp文件对应的工作区目录
let workspaceUri = vscode.Uri.file(path.dirname(curFileName));
//打开当前cpp文件对应的工作区
vscode.commands.executeCommand('vscode.openFolder', workspaceUri).then(success => {
console.log('open folder result:', success);
//打开工作区的第一个lauch配置(本例配置为一个attach调试)
const config = vscode.workspace.getConfiguration('launch', vscode.workspace.workspaceFolders[0].uri);
const configurations = config.get('configurations');
//获取UI的exe进程号
cp.exec('tasklist', function(err, stdout, stderr){
if(err){return console.log(err);}
stdout.split('\n').filter(function(line){
var p = line.trim().split(/\s+/), pname = p[0], pid = p[1];
if(pname.indexOf('TestGui.exe') >= 0 && parseInt(pid)){
//修改processId为当前的UI进程ID
configurations[0].processId = pid;
//启动调试器,attach到该进程上开始调试
vscode.debug.startDebugging( vscode.workspace.workspaceFolders[0], configurations[0], null);
}
});
});
});
};
简单来说就是,通过TestGui.exe启动vscode打开某个cpp文件时,插件就会触发,首先获取该cpp文件的路径,然后打开对应的workspace。获取该workspace的第一个lauch配置,我的第一个lauch配置如下(在workspace的launch.json文件中):
"configurations": [
{
"name": "testAttach",
"type": "cppvsdbg",
"request": "attach",
"processId": "${command:pickProcess}"
},
{
可以看到这是一个attach调试的配置,这里有几点注意事项:
1 type :如果你使用的是windows的cl.exe这个编译器,那么这个type一定要填cppvsdbg,gdb编译器的话,type填的是cppdbg.
2 request: 因为我的需求是attach到UI进程上调试,所以填的是attach。如果是需要新启动一个进程进行调试,这里需要填launch。
3 processId:这里可以填${command:pickProcess},即调试启动时让用户选择一个进程附加上去。也可以直接填一个固定的process Id,这样调试启动时就直接附加到该进程号对应的进程上了。但是这两种方式都不符合我的需求,因为第一种方式,需要手动选择一个进程才能启动调试,我需要的是自动附加到UI进程。而由于我每次启动UI进程时,UI进程分配到的进程ID都不一样,所以第二种填一个固定进程ID的方式也不行。所以这里采用的方法是,在插件中,根据tasklist这个shell命令实时搜索当前TestGui.exe进程的进程ID,然后修改launch中的processId, 这样插件就可以自动attach到当前的UI进程上了。
五 UI进程打开cpp文件
HMODULE hDllLib = LoadLibraryA("XXX\\TestDll.dll");
if (hDllLib == nullptr)
{
//cout << "load library failed!" << endl;
}
else
{
//cout << "load library successfully!" << endl;
auto pFunc = GetProcAddress(hDllLib, "TestInterface");
if (pFunc != nullptr)
{
pFunc();
HINSTANCE hRtn = ShellExecute(NULL, (LPCWSTR)L"open", (LPCWSTR)L"\"D:\\Users\\UserName\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe\"",
(LPCWSTR)L"D:\\XXX \\TestAttach.cpp", NULL, SW_SHOW);
}
else
{
//cout << "can not get TestInterface!" << endl;
}
}
利用ShellExecute这个WINDOWS的API使用Vscode打开指定的cpp文件。此时cpp文件被打开后,就会自动触发上面的vscode插件,自动attach到UI进程上。
至此第一个vscode插件开发完成,可能有的地方描述不太准确,这也是我的第一个博客,希望大家积极批评指正,今天就写到这吧。
参考资料:https://www.cnblogs.com/liuxianan/p/vscode-plugin-common-api.html
一个vscode自动attach进程的插件开发实例相关推荐
- 编写一个VSCode插件
原文链接: 编写一个VSCode插件 - 愧怍的小站 自从使用过 VSCode 后就再也离不开 VSCode,其轻量的代码编辑器与诸多插件让多数开发者爱不释手.同样我也不例外,一年前的我甚至还特意买本 ...
- python发送邮件 python发送qq,163,sohu, xinlang, 126等邮件 python自动发邮件总结及实例说明...
python发邮件需要掌握两个模块的用法,smtplib和email,这俩模块是python自带的,只需import即可使用.smtplib模块主要负责发送邮件,email模块主要负责构造邮件. sm ...
- 个人建议:设置Alt+S快捷键来控制VSCode自动保存切换功能
经常要修改配置文件或者组件Vue,但是自动保存如果设置了就会导致还没输入完成一个完整代码行,就自动格式化(当时这种情况真的想骂人),但平时编辑Vue页面文件又不想每次都去Ctrl+S保存(毕竟键盘死的 ...
- 推荐一个代码自动完成的工具AutoCode
本文转载:http://www.cnblogs.com/xiaoxiangfeizi/archive/2012/07/24/2605884.html 最近发现了一个代码自动完成工具AutoCode,特 ...
- 【Android 逆向】代码调试器开发 ( 代码调试器功能简介 | 设置断点 | 读写内存 | 读写寄存器 | 恢复运行 | Attach 进程 )
文章目录 一.代码调试器功能简介 二.Attach 进程 一.代码调试器功能简介 代码调试器功能 : 设置断点 : 无论什么类型的调试器 , 都必须可以设置断点 , 运行到断点处 , 挂起被调试进程 ...
- Linux OOM 自动杀死进程(转)
Linux OOM 自动杀死进程 问题描述: 今天上班后,登录一台内网测试服务器,发现部分进程失踪 (Nginx/PHP-FPM/MySQL/Crond). 解决方法: 1.首先启动这些进程,保证正常 ...
- java list加入listview_Android ListView自动生成列表条目的实例
activity_list.xml文件代码如下: xmlns:android="http://schemas.android.com/apk/res/android" androi ...
- java socket发送定长报文_一个基于TCP协议的Socket通信实例
原标题:一个基于TCP协议的Socket通信实例 1. 前言 一般接口对接多以http/https或webservice的方式,socket方式的对接比较少并且会有一些难度.正好前段时间完成了一个so ...
- vscode自动加前缀_详解VScode自动补全CSS3前缀插件以及配置无效的解决办法
1.在vscode中搜索Autoprofixer 2.在安装完成之后要配置 在需要添加前缀的css文件上,右键点击命令面板,输入Autoprefixer CSS就好啦 ps: 如果想要兼容性最好的话, ...
- 【chorme插件开发】第四节:html+js实现的功能插件开发实例
###html+js实现的功能插件开发实例 插件结构 icon.pngpopup.htmlpopup.jsmanifest.json manifest.json文件配置 { "manifes ...
最新文章
- 多表查询事务DCL权限管理
- c语言字符指针初始化赋值,C语言_指针变量的赋值与运算,很详细详解
- 江苏省计算机考试Python用书,【关注】Python列入高考内容以及全国计算机等级考试!...
- php框架--php框架的连贯查询实现原理
- O2O概念实践案例: Giftly改变送礼方式
- 力扣116. 填充每个节点的下一个右侧节点指针(JavaScript)
- WPF 去除头部,实现拖动
- 虚拟机下liunx安装jdk
- iOS8过渡到iOS9,Xcode6过渡到Xcode7
- 中国行政区域(县区级带坐标经纬度)
- 【Unity gradle打android包网络连接超时错误 connec xxx ttime out】
- 关于手画猫,耳朵涂颜色
- 关于win11系统网络连接有效但是无法正常上网的解决办法
- 伊拉克COR证书电子电器
- 人工智能对学计算机的影响,计算机专业大学生对人工智能对人类的影响分析.docx...
- 努比亚android11,努比亚Play开测Android11 填写基本信息即可
- MySQL 5.6.22绿色版安装
- DNN中的BP和RNN中的BPTT推导
- 【苹果CMS技术教程】苹果CMSV10怎么更换模板
- 日历控件QCalendarWidget