用C#为Notepad++写插件:完善IDE调试体验、使用共享项目、实现窗口停靠

作者:V君 发布于:2019-1-5 21:57 Saturday 分类:折腾手记

TL;DR

完善IDE调试体验

1) 在 Notepad++ 插件目录创建文件符号链接,指向 bin\debug\x86(或x64)\ 里的 dll
2) 将项目属性-调试选项卡-启动操作的外部进程指定为 Notepad++ 的绝对路径
3) 设置断点,F5!

使用共享项目

1) 新建共享项目,命名 Kbg.NppPluginNET.PluginInfrastructure 这样可以一致命名空间
2) 将 PluginInfrastructure 里的代码文件移动过去
3) 在插件项目中添加共享项目引用, 这样一份基础设施代码就能在多个项目之间共享

实现窗口停靠

1) 从官网插件开发向导页面找C#插件示例中参考窗口停靠的具体实现。在GitHub也有在线版
2) 新建一个窗体,命名 SayHiForm,延续上回命名习惯
3) 将示例代码应用到项目中,按 F5 键启动调试验证实现。可以在 Gogs 上查看最终实现

点击查看原图

~扯谈时间~

在上一篇文章里我们搞清楚了如何开始用 C# 为 Notepad++ 写插件。让我们继续折腾,这次一共有3个折腾点,分别是完善调试体验、用共享项目避免重复代码还有实现窗口停靠。让我们从第一个折腾点开始。

按照TL;DR的步骤操作下来,现在可以命中断点了,也能查看和修改变量值以及拖动执行代码,略遗憾的是编辑并继续不可用。提示未加载程序集时不允许,可能是 DllExport 修改 DLL 导致。总而言之,能打断点已经是很好的体验了。非要在调试时想要编辑并继续也不是不可以,只要另起一个项目作为调试启动入口来调用这个程序集,那么在调试时也是可以编辑并继续的,只不过你得而外地为调试入口做一些适配,从而弥补调试入口和实际被 Notepad++ 加载运行时的差别。扯完这个折腾点之后让我们简单扯扯代码共享项目。

说到代码共享项目那就得先聊聊过去,在没有这种项目类型时,我是如何管理重复出现于多个项目的代码集。在那个时代,我的解决方案有两种,分别是将其独立成为类库,或者用目录符号链接。这两种方法相对于代码共享项目来说都是有明显缺陷的,拿这次我们折腾的,带非托管导出函数的程序集来说,就得把代码放入当前项目中,导出函数不应该出现在引用的程序集;而符号连接虽然能算作当前项目的代码文件,然而命名空间不能与项目名称保持一致,从规范层面来看有些尴尬。用了共享项目之后这两个问题得到了彻底的解决。共享项目能扯的并不多,最后是这次的重头戏--可停靠窗口。

说到可停靠窗口,我要先小声 BB 一下,现在能找到的,能在 Windows 下离线使用的,带实时预览窗格的 Markdown 编辑器中,大部分布局都是文本编辑在左边,预览窗格在右边。只要把预览窗格做成可浮动、停靠的活动面板,这就完美的满足了我这种挑剔家伙和大众普遍习惯的需求。就算是能把预览窗格移动到左边的 vs code,它也不能实现浮动窗口。

回归主题让我们继续吧!进入官方推荐的插件示例项目一看,略震惊。具体实现只需要短短几行代码把窗体句柄按照指定的姿势丢给 NPP,它就能自己管理停靠! TL;DR 里已经写的很清楚,这里就不再啰嗦。

才如果你把整个解决方案Check出来,会发现上一篇文章折腾的 HelloNppPlugin 插件项目并没有使用共享代码项目,这是有意而为之,让内容和文章描述尽可能一致,避免初看的读者受到影响。

这次就扯到这里,下次关于 NPP 插件的文章估计是 Markdown 插件发布的时候了。

标签: 软件开发 插件 C# Interop 调试技术

评论(0) 引用(0) 浏览(1333)

用C#为Notepad++写插件:解决在VS2017生成导出函数不全——起手式

作者:V君 发布于:2019-1-5 3:27 Saturday 分类:折腾手记

TL;DR

1) 寻找项目模板, 从 MarkdownViewerPlusPlus 插件源代码中提取模板,相对官方模板较完善
2) 用 3F 的 DllExport 代替模板中的 NppPlugin.DllExport.MSBuild, 补全导出函数
3) 编码调试, Enjoy!

嫌TL;DR太少看不懂? 那就稍稍写个示例来解剖一下青蛙吧!

点击查看原图

新建一个类库项目,这次起名 HellpNppPlugin(源代码)。然后从 MarkdownViewerPlusPlus 插件源代码中把插件基础设施 (PluginInfrastructure) 目录中除了 DllExport 文件夹之外的全部代码文件搬进项目中。

修改 UnmanagedExports.cs 去掉 NppPlugin.DllExport 命名空间引用,这时候的源代码是不能通过编译的,不要急,保存解决方案继续。

下载 3F 的 DllExport 批处理,放到解决方案根目录。打开一个命令行转到这里,加参数 -action Configure 执行,稍等片刻就会弹出一个小窗口,下拉选择要操作的项目,点击 Installed 复选框,这时候窗口展开许多选项,中间填命名空间的下拉文本框选择 System.Runtime.InteropServices 然后点击右上角的 Apply 按钮。命令行刷出几行日志,窗口消失了。回到VS提示文件被外部修改,点击重新加载。打开项目属性,允许不安全代码,增加两个系统库程序集引用,分别是 Winform 和 Drawing。

准备工作不多,接下来就到令人心动的具体实现了!

把 Class1.cs 重命名成 Main.cs 包括里面的类也跟着重名名,回到 UnmanagedExports.cs 引入 Main 的命名空间,在 Main 添加导出函数需要的成员。分别是1个指定插件名称的字符串和4个方法。在 CommandMenuInit 方法增加下面这行代码:

PluginBase.SetCommand(0, "Say hello", () => MessageBox.Show("Hello NppPlugin by C#!"));

编译,去 debug 目录找 DLL 会发现 DllExport 已经帮我们分别生成了32和64位的 DLL。复制对应版本到 NPP 的插件目录,启动 NPP,Plugins 菜单第一个就是咱们插件的名称,展开子菜单「Say hello」点击可以弹出 Hello 消息框。

示例到此结束!

~吐槽时间~

最近工作上需要写技术文档,想用 MarkDown 撰写后或导出 PDF。找了大半天并没有发现太好用的本地编辑器,主要是对界面太挑剔,我想要预览窗格在左边,而文本编辑窗格在右边,筛选下来的就只有 Smark 和这次提到的 NPP 插件。他们都有不同程度的问题:S 的编辑器很糟糕,而且经常会崩溃;NPP插件渲染斜体不工作而且导出PDF的中文显示方框乱码,用起来仍然不便。意外发现这个NPP插件居然是100%用C#实现,这下有意思了,看看能不能自己造个轮子,我要用 Cef 来渲染!

一拍脑门想到还有 vs code,用它来写 Markdown 带实时预览(预览窗格也能拖到左边),通过插件导出可以改变预览样式也能导出 html,就纠结要不要弃坑…… 还是继续吧,用 NPP 更轻更习惯一些。另外 NPP 能把停靠的窗格从主窗体拆离出来,这一点 vs code 做不到,只能勉强开新的实例。继续折腾还能长姿势!

一开始就栽了个大跟头,官方 C# 插件项目模板根本不能正常生成,一番折腾之后生成出来的 dll 放进插件目录不能正确加载。咕狗发现有人提到依赖特定VS版本才能生成完整的导出函数,回来用CFF分析工具查看果然导出函数不全。即使是相对完善的 MarkdownViewerPlusPlus 插件源代码,生成出来的导出函数依然不全,难道只能用低版本的 VS? 不! 应该还能再抢救一下。

抱着「C# DllExport」去咕狗,啃各种流程原理,原来要先反编译成 il 然后魔改,再用 VC++ 工具链中的 lib.exe 掺一脚,最后才能生成带导出函数的托管 DLL。再继续找就发现了 3F 的看起来像是脚手架一样的批处理。用它成功地在 VS2017 编译出完整导出函数的 DLL。NPP 插件的开发终于得以继续进行。

原来托管的 DLL 也能添加导出函数给原生应用程序调用,长姿势了!

标签: 软件开发 插件 C# Interop

评论(0) 引用(0) 浏览(1767)

C#字典添加项报错“索引超出了数组界限”,是M$的BUG吗? NO! 前人傻逼!

作者:V君 发布于:2018-11-16 11:29 Friday 分类:填坑经验

TL;DR: 给我用并发字典,如果是3.5及以下,就锁起来! 

依旧是陈年老项目,最近开始发现有大面积丢数据的情况,在日志看到大片的索引越界异常. 

Exception: 索引超出了数组界限。
 在 System.Collections.Generic.Dictionary`2.Insert(TKey , TValue , Boolean )
 在 System.Collections.Generic.Dictionary`2.Add(TKey , TValue )

乍一看,还以为是M$的BUG,从系统库内部爆出来的非预期异常.

按预期,字典能爆的异常应该只有重复key.

在阅读代码之前先用关键字喂狗,吐出爆栈,看到竟态现象.
而且,字典的状态一旦坏掉就会一直坏下去...

开始阅读代码,果然 -- 字典添加和移除操作在不同线程,且未加锁 -- 3.5没有并发字典

简单加锁发布修复版本交差.

标签: 软件开发 C#

评论(3) 引用(0) 浏览(2079)

在树莓派上使用C#实现:通过按钮操作PWM调节LED灯亮度

作者:V君 发布于:2018-10-28 2:45 Sunday 分类:折腾手记

TLDR:

源代码:SVNGit

依赖库:WiringPi


操作步骤:

0)树莓派上需要安装好mono软件包并启动远程调试器

1)从依赖库官网下载源码包并在树莓派上通过自带的构建脚本进行安装;

2)引出第18pin(只有这pin支持PWM),经过330欧姆电阻接到LED灯,另一边回到负极。

3)再引出两个GPIO(源代码里是17和27)经过同样的电阻接按钮,另一边回到3.3v正极。

4)在VS里打开源代码,连接到树莓派上启动调试。

此时LED灯会亮起来,并能够通过两个按钮调节亮度


原来LED亮度是用PWM的占空比来控制的,学到新姿势了 乂目

标签: 软件开发 树莓派 C# 嵌入式

评论(0) 引用(0) 浏览(1267)

在VS15上远程调试Mono应用程序:原来还有这么舒服的姿势!

作者:V君 发布于:2018-10-27 22:48 Saturday 分类:折腾手记

小试一把确认可行之后就来写博文了,稍后再扯,先TLDR:

关键字「mono remote debug」喂狗,吐出「MonoRemoteDebugger」插件。

顺着介绍导航到其GitHub仓库看用法

0)目标机器需要先安装Mono的软件包,这次用的是「mono-devel」
1)下载预编译版本zip到目标机器,解包执行,进入等待状态。
2)在VS里装好插件,新建一个控制台项目,
  点击菜单「
MonoRemoteDebugger -> Debug with Mono (remote)
  在弹出的对话框输入目标机器IP,点击连接按钮。
3)当前应用程序会自动推送到目标机器并以调试模式启动,
  如果在主线程设置断点,将会在断点处停下来,此时可以查看变量值。

需要注意的是Mono调试器并没有原生的那么强大,做不到编辑并继续的体验。
受到远程调试器完善程度的影响,目前还不支持用户线程断点。

不过没关系能打断点看变量值已经很奢侈啦!

进入闲话时间

还记得之前为了调试树莓派GPIO所做的C/S远程控制接口吗?
最近忽然想玩PWM,想试着用它来控制LED灯的亮度。
首先想到的是树莓派自带的Remote gpio功能,然而资料并不多,只能找到py的,没有C#的。
之后换了个想法,如果能直接在上面跑调试那该多好。
虽然知道可以在上面直接安装MonoDevelop来调试,但这货太过于臃肿。
又试着去咕狗看看,结果就找到这货啦!


标签: 软件开发 树莓派 C# 嵌入式 调试技术

评论(0) 引用(0) 浏览(1386)

Powered by emlog 去你妹的备案 sitemap