关于如何做一个Source Insight外挂插件的全过程都已经写完了,这么一点东西拖了一年的时间才写完,足以说明我是一个很懒的人,如果不是很多朋友的关心和督促,恐怕是难以完成了。许多朋友希望顺着本文的思路也作一个类似于TabSiPlus功能的Source Insight外挂插件,抱歉让他们等了这么长时间,看了本文或许能让大家消消气(大头在后面)。其实即使不是为了给Source Insight做外挂插件,本文的很多方法都可以用于给其它软件做外挂。

尽管本文介绍了做TabSiPlus外挂插件的完整过程,但是要做一个有使用价值的外挂插件还有很多细节要注意,首先是稳定,插入到Source Insight进程中的代码一定要考虑周到,仔细地测试所有分支,确保不能频繁地挂死Source Insight;其次,附加的功能一定不能干扰Source Insight的正常工作,比如窗口消息的处理;最后就是在界面上要能和Source Insight融为一体,插件创建的窗口一定不能覆盖Source Insight的窗口。
    
    以上都是空话,现在用具体的例子来说几个细节,比如TabsiPlus提供了直接根据标签关闭文档窗口的功能,由于文档窗口创建的时候已经获取到窗口的句柄,所以TabsiPlus的第一个版本就使用DestroyWindow() API直接关闭了文档窗口,从外表看确实大到了效果,但是却隐藏了一个BUG,那就是虽然窗口被关闭了,但是Source Insight并不知道文档窗口被关闭了,相应的文件依然处于打开状态,如果文档修改过,这样关闭窗口甚至不会提醒用户保存文档。在自己的程序中关闭窗口当然直接DestroyWindow()就行了,但是既然你的代码是“寄人篱下”,就要按照“别人”的规矩来。通过Spy++观察Source Insight窗口的消息,发现Source Insight窗口只对WM_CLOSE消息会有正常的反映,也就是说Source Insight可能在OnClose()中处理了关闭文件和提示保存修改的操作(很奇怪DestroyWindow()后为什么没有触发Source Insight的OnClose()处理被调用,看来远程注入的代码确实有很多需要注意的地方),后来的版本使用SendMessage将一个WM_CLOSE消息发给文档窗口,这样就很好地解决了这个问题。
    
    上面的问题还没完,让窗口消失就算是关闭了吗,有没有考虑窗口的Focus? 如果关闭某个拥有“焦点(Focus)”的子窗口,Windows会激活此焦点窗口的一个兄弟窗口,通常是上一个拥有焦点的窗口,这个相信使用Windows的人都知道,我也是这么认为的,但是,这一点在外挂中失灵了,在TabSiPlus的线程中,关闭当前拥有焦点的文档窗口后,其它的文档窗口标题栏竟然都是灰的,也就是Source Insight的MDIClient窗口没有选择上一个焦点窗口激活,怎么办?看看TabSiPlus中关闭文档窗口的代码:

void CTabBarsWnd::CloseSIWindow(CSiWindow*& pWindow)
{
  ASSERT(pWindow);

HWND hPrevActive = NULL;
  if(pGlobalActiveSIWindow != NULL && pWindow != pGlobalActiveSIWindow)
  {
    DebugTracing(gnDbgLevelNormalDebug,_T("CTabBarsWnd::CloseSIWindow() pGlobalActiveSIWindow = %x"),pGlobalActiveSIWindow);
    hPrevActive = pGlobalActiveSIWindow->GetSafeHwnd();
    m_iLockUpdates++;
  }

pWindow->SendMessage(WM_CLOSE, 0, 0);//now close it!

if(hPrevActive != NULL)
  {
    ::PostMessage(::GetParent(hPrevActive), WM_MDIACTIVATE,(WPARAM)hPrevActive, 0);
  }
}

核心只有一句:
pWindow->SendMessage(WM_CLOSE, 0, 0);//now close it!
却要围绕它做很多事情。

再来看一个问题,有没有考虑过Tab标签栏上的标签与实际打开的文档窗口个数不一致的情况?虽然我们Hook可MDI_CREATE消息,但是依然有一些窗口创建是TabsiPlus插件无法感知的,比如Source Insight支持内置宏语言,通过宏进行窗口操作TabsiPlus插件无法感知,还有一种情况是Source Insight对于一些不激活的文档通常不是立即创建窗口,而是在激活的时候才创建窗口显示文档,当用户通过Windows菜单看到的已经打开的文件与你的Tab标签栏不一致会怎么想?没有好的办法,TabSiPlus使用一个定时器处理这种不一致,具体代码在CTabBarsWnd::OnTimer()中。

还有一个问题,如何安全地关闭外挂插件?有一种方法先关闭Source Insight,然后关闭加载器TabSiHost.exe,然后再打开Source Insight。让自己接受这种方案都很难,更何况别人,如果能够在插件中提供一个界面,通过用户选择可以直接退出插件就好了,实现这一点关键是Source Insight内部关闭Tab标签窗口后如何中止加载器TabSiHost.exe,如果不中止TabSiHost.exe,TabSiHost.exe会再次加载TabsiPlus.dll插件。TabsiPlus通过内核对象完成与TabSiHost.exe的同步:

void CTabBarsWnd::ShutDownTabSiPlus()
{
  HANDLE hAnotherTabSiHostEvent = NULL;
  LPCTSTR szGlobalKernelName = _T("Local//TabSiHostIsAlreadyRunning");
  hAnotherTabSiHostEvent = CreateEvent( NULL, TRUE, FALSE, szGlobalKernelName );

DWORD dwer = GetLastError();

if(dwer == ERROR_ALREADY_EXISTS)
  {
    ResetEvent( hAnotherTabSiHostEvent );
  }
  ::CloseHandle(hAnotherTabSiHostEvent);
  g_pSiMDIClientWnd->SetManaging(false);
  DestroyWindow();
}

还有,TabSiPlus内部窗口之前传递数据都是通过自定义消息进行的,原因就是Tab标签窗口与Source Insight的窗口是工作在不同的线程中的,在线程之间只有句柄是安全的,向窗口句柄发送消息要比直接操纵数据要安全。还有,当使用了Source Insight的查找字符串功能时,Source Insight会打开一个窗口显示搜索的结果,这个窗口的窗口类名和代码窗口一样,都是si_Sw,但是其窗口标题却和代码窗口的标题不一样,这个要区分。其它的细节还有很多,就不一样列举了,具体看代码吧。

罗嗦了半天,代码在哪里?本来想随本文一起上传的,但是这个Blog上传附件太麻烦,只好放到我的CSDN资源里了,大家可以到我的空间下载源代码。本文附带的代码是一份精简的TabSiPlus插件代码,为了大家理解代码,我去掉了全部装饰性的代码和附加功能代码,包括很多预防性代码,这样做地目的就是为了大家在学习源代码时能够将注意力集中在框架上而不是枝节琐事。尽管如此,这是一个完整的可工作的Tab标签栏,演示了本文写的全部内容。除了我的代码之外,源代码中还使用了一些自由代码,使用时请注意相关作者的权利要求。

代码的编译很简单,用VC 6.0打开直接Build就行了,为什么不升级到VC7 or VC8?其实我很懒。调试的时候注意相关的资源文件要在同一个目录中,TaiSiHost.exe的调试比较简单,直接加载就行了,调试TabSiPlus.dll比较麻烦,首先关闭已经打开的Source Insight程序,然后在Project Setting/Debug 窗口中设置“Executable for debug session:”为Source Insight的主程序,通常是Insight3.exe,再然后运行TabSiHost.exe,最后就可以按F5开始调试了。整个过程就是:按下F5后,VC根据调试设置启动insight3.exe,已经运行的TabSiHost.exe发现启动了Source Insight,就会远程代码注入到insight3.exe,于是insight3.exe就会加载TabSiPlus.dll,这样就可以调试了。

Source Insignt文件标签外挂:TabSiPlus的下载地址:
http://www.winmsg.com/download/tabsiplus.zip

给Source Insight做个外挂系列之六--“TabSiPlus”的其它问题的更多相关文章

  1. 给Source Insight做个外挂系列之三--构建外挂软件的定制代码框架

    上一篇文章介绍了“TabSiPlus”是如何进行代码注入的,本篇将介绍如何构建一个外挂软件最重要的部分,也就是为其扩展功能的定制代码.本文前面提到过,由于windows进程管理的限制,扩展代码必须以动 ...

  2. 给Source Insight做个外挂系列之一--发现Source Insight

    一提到外挂程序,大家肯定都不陌生,QQ就有很多个版本的去广告外挂,很多游戏也有用于扩展功能或者作弊的工具,其中很多也是以外挂的形式提供的.外挂和插件的区别在于插件通常依赖于程序的支持,如果程序不支持插 ...

  3. 给Source Insight做个外挂系列之五--Insight “TabSiPlus”

    “TabSiPlus 外挂插件”主要有两部分组成,分别是“外挂插件加载器”和“插件动态库”.“插件动态库”完成Source Insight窗口的Hook,显示Tab标签栏,截获Source Insig ...

  4. 给Source Insight做个外挂系列之四--分析“Source Insight”

    外挂的目的就是将代码注入到其它进程中,所以必须要有目标进程才能完成注入,而所谓的目标进程通常是某软件的一部分或者是全部,所以要对目标程序有深入地了解.一般外挂都是针对某个应用程序开发的,其装载.运行都 ...

  5. 给Source Insight做个外挂系列之二--将本地代码注入到Source Insight进程

    上一篇文章介绍了如何发现正在运行的“Source Insight”窗口,本篇将介绍“TabSiPlus”是如何进行代码注入的.Windows 9x以后的Windows操作系统都对进程空间进行了严格的保 ...

  6. Source Insight 3.X 标签插件v1.0发布

    Source Insight可以说是一款程序员必备的开发/阅读源码工具,美中不足的是SI没有标签栏,多个源码之间切换很不方便,于是我就乘闲暇之余写了该作品sihook:标签插件;不过严格意义上来说si ...

  7. Source Insight 插件

    一提到外挂程序,大家肯定都不陌生,QQ就有很多个版本的去广告外挂,很多游戏也有用于扩展功能或者作弊的工具,其中很多也是以外挂的形式提供的.外挂和插件的区别在于插件通常依赖于程序的支持,如果程序不支持插 ...

  8. source insight 编程风格(持续更新)

    1.字体Source Code Pro 出身于豪门Adobe,从名字上来看就知道是转为编码而生的.基本上也是拥有前面所提的编程字体的所有要素的.这个字体基本上具有编程字体所需的所有要素:等宽.支持Cl ...

  9. Linux下Source Insight的安装和汉化

    原创文章,转载请注明出处. 工欲善其事,必先利其器.Source Insight绝对是阅读C和C++代码的利器,另外,Source Insight的体量很小,安装便捷,显示直观,比vim+cscope ...

随机推荐

  1. 各大安卓应用市场APP上传提交与收录

    360 提交网址 应用宝 提交网址 百度 提交网址 91 提交网址 安卓 提交网址 PP助手 提交网址 小米 提交网址 华为 提交网址 OPPO 提交网址 魅族 提交网址 乐视 提交网址 豌豆荚 提交 ...

  2. 安装Yeoman,遇到的问题

    在安装Yeoman遇到了一些报错,具体的步骤就不多说了,直接上码,具体的两处报错的地方. 第一个,创建webapp,直接报权限的错误,这时才留意到在它之前还有一个错误. [root@iZ289zd8c ...

  3. github安装&初探

    主要记录安装中的问题: 1 centos 5和6的epel源需要不同的包来更新 Centos 5.x wget http://dl.fedoraproject.org/pub/epel/5/x86_6 ...

  4. vue学习

    2016年12月2日 今天学习Vue.js,对于未知的知识,一脸懵逼.记录学习新知识的路程,为以后学习更多的新知识一个引导.以后学会了之后再回来看看, 回忆一下会与不会的区别在哪.这样以后学习可以更快 ...

  5. iOS开发UI篇—核心动画(基础动画)

    转自:http://www.cnblogs.com/wendingding/p/3801157.html 文顶顶 最怕你一生碌碌无为 还安慰自己平凡可贵 iOS开发UI篇—核心动画(基础动画) iOS ...

  6. centos7修改主机名

    临时修改: hostname centos7 永久修改: # hostnamectl set-hostname cen07

  7. 前后台json数据绑定——way.JS

    依赖于JQ 01_页面值-页面值绑定.html 02_List绑定多个相同模型.html 0201_先set,再DOm添加.再get.html 03_绑定多个不同模型.html 04_继承03用类.方 ...

  8. 使用ajax.dll时js脚本错误-XXX未定义

    操作系统:Windows 7 IIS:7.5 ajax.dll现在用的比较少,但是以前的项目有这个,使用的时候很容易出现这个错误,因为总是会遗漏配置. 使用ajax.dll时,js脚本错误,无法调用后 ...

  9. 神经网络及其PID控制

    一.人工神经元模型 1.突触权值(连接权) 每一个突触都由其权值作为特征表征,各个神经元之间的连接强度由突触权值来表示.与神经元相连的突触上,连接的输入信号通过权值的加权进入神经元的求和单元. 2.求 ...

  10. linux vi命令

    >>>>>>>>>>>>>>>>>>>> 2016.12.6: vi是交互式的编 ...