C#与Nodejs的交互实现

对C#与Nodejs有复杂交互场景的,请移步EDGE

我的使用场景相对简单,就是Node向C#发送命令,C#执行完成后反馈给Node,并且希望总是同一个进程在处理数据。没有使用EDGE的原因是,不喜欢它的杂交的语法,而且我喜欢将事情简单化。

我的实现方法初步定为:Node使用Spawn运行一个C#程序,在需要向C#发送命令的时候,调用C#的process.stdin.write,然后使用process.stdout.on(‘data’)重定向C#的输出到Node。这样就可以已相对分离的方式实现我的需求。

实现特别简单,问题却马上来了。

Continue reading

在分层窗口上显示普通控件

一直以来,有一个魔咒一样的说法折磨着Windows界面开发者,就是Layered窗口(即分层窗口,也即有WS_EX_LAYERED属性的窗口)不能显示普通控件(如Edit等)。原因大家都知道,就是分层窗口使用的是32位位图控制显示效果,而普通控件使用的是GDI绘制界面,GDI会将绘制区域的Alpha值设置成0,导致普通控件显示不出来或者显示出很奇怪的效果。这就挡住了很多DirectUI库、普通界面开发者的脚步。而有Caret的窗口,也使这一步变得更麻烦,因为Caret也是Gdi绘制出来的,也同样无法显示。

已有的解决办法无非三种:

  1. 完全手绘需要的控件,例如List、Tree等,而遇到Edit这成本就高了,因为Edit的复杂度非常高;
  2. 使用双窗口,两个窗口进行位置同步,但这样在焦点的处理上比较麻烦(下层窗口在Edit获取到焦点的时候,任务栏上会显示成失焦);
  3. 使用RichEdit的Windowless效果,如Soui就是这样做的。RichEdit是个好东西,但Windowless的RichEdit并不是所有人都能驾驭得了的。

我心里一直有个解决的办法没有时间实践,这个周末终于实验结束并完成Demo,方法如下。

Continue reading

VS的Profiler不再蓝屏[续]

重装了系统,使用Profiler发现蓝屏,幸亏以前有记录解决办法:http://www.hufuman.biz/?p=160,兴高采烈地打开下载链接的时候,发现微软已经把对应的HotFix删除了!完全被忽略了的感觉,于是各种搜索后,发现有哥们说如果是VS2008 Pro版的话就没问题了,我是不是太单纯,以至于下载安装开启Profiler的那一刻,又蓝屏了。

然后各种搜索,一共发现三个微软提供的下载地址,全都失效了,实在是太彻底了。

继续搜索,发现一个神奇的网站:http://astra.digi2.jp/a/e/list-of-vs2008-hotfix.html。它的神奇之处在于,直接指向了各种HotFix的下载地址,虽然这些链接打开以后竟然是要求以Email的方式发送真正的下载地址,but it works!

为防止这个网址也挂掉,贴出几个HotFix的地址:

调皮的GDI矩形

使用Gdi的过程中,总能遇到或多或少的小惊喜。

需要实现一个画矩形的功能,却发现远比想象中要麻烦得多。画矩形有几个办法:FillRect、Rectangle、LineTo、FrameRgn、ExtTextOut等。实际使用起来发现前四个各有各的问题:

  1. FillRect,不能实现描边,且描边宽度无法控制
  2. Rectangle,一是并不是在指定的Rect里画的矩形,而是以指定的矩形边框为中心画。二是坐标有点飘忽不定的,最简单的验证方式是以GetClientRect得到的矩形以不同的宽度画矩形即可。
  3. LineTo,在宽度超过2以后,线的两端会超出指定的坐标,并且线两端是圆的,跟需要的不一样。
  4. FrameRgn,由于涉及到Rgn,性能有损失。

最终使用ExtTextOut实现了需要的功能:

 

支持Alpha的DC

重写界面库的过程中,需要实现带Alpha值的Text、Shape等,于是实现了个AlphaDC类。

原理很简单,步骤表示如下:

为了提高效率,实现里使用了SSE加速,其实就是用汇编实现了位值的操作,比代码直接实现会好一些。

Continue reading

遭遇弱符号

在重写类反射创建对象的方法,却遭遇了弱符号。

在每个类的实现中,使用以下方法

 

进行类信息的注册。

Continue reading

2014.5 近况

好久没有更新博客。

今年最大的变化应该是换了新的工作,离开了C++阵营,也离开了打拼接近4年的团队。

个人项目:

  1. excel2db,工作需要的一个从Excel导入数据到Db的一个工具,时间关系暂时停止
  2. hosts_editor,Windows下编辑Hosts的便利工具,尤其适用于经常需要在不同Hosts之间切换的情况,已完成
  3. filesiconv,Windows下用于一次性将多个文件在不同编码间转换的工具,已完成
  4. spy2nd,Spy++的增加版本,已实现窗口的查找及基本信息显示,时间关系暂时停止
  5. colorpicker,Windows下用于取屏幕色RGB值的工具,带放大镜功能,已完成
  6. crashstat,用于抓取、提交程序的崩溃信息、崩溃分析以及友好的Web展示,已完成架构及部分模块的Wiki说明,进行中
  7. 用Webkit(Libcef)和Qt分别朋友封装了一个H5框架,结论是Qt的Webkit还是嫩了点,对H5、CSS3的一些特性的支持还是弱了太多,经常莫名的崩溃。

新的工作比较忙,基本没有时间搞点自己的东西,一会C#、一会Java、一会Nodejs,对新公司也处在了解过程中,更多地接触和了解管理方面的内容,也有了一些直面惨淡的进度和各种沟通的经验。

下一步的业余时间应该集中在crashstat上,尽快完成自己的心愿吧。

SxSHacker

从VS2005开始,VS的工程如果没有设置为静态链接CRT的话,开发的程序在普通用户的电脑上运行,可能就会提示:

由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题

这个问题困扰了很多朋友。

最近写了一个工具:SxSHacker,专门用来导出Windows下开发的程序,需要的Runtime。

使用这个工具前,需要在VS的工程设置中添加一个宏定义:

然后使用SxSHacker,按照使用说明,导出所需要的运行时,发布程序时,把运行时跟自己的程序一起发布即可。

SxSHacker下载地址:

https://github.com/hufuman/sxshacker/blob/master/sxshacker_x32.exe?raw=true

Github工程地址:

https://github.com/hufuman/sxshacker

使用Sqlite3的Bug一例

将Sqlite3的功能封装了一个类,方便自己使用,但是在上一个项目发布的前夕,发现一个数据库无法使用的问题。

具体情况如下:

有一个SQLITE3的DB文件,保存了程序的配置信息。在安装包的最后中会根据用户的选择设置该DB里的一个值。大概的伪代码如下:

主要问题在ensureDB()方法中,乍看上去一点问题也没有,表格如果存在,则返回true;表格如果不存在,则建立表格。感觉只要文件系统正常,这里基本不会出现问题。但是恰恰是这里的问题。主程序在初始化过程中,ensureDB()总是返回false,但是如果该Table提前存在的话,则不会有问题。

 

而这个问题仅仅在安装包和主程序同时修改该表格的时候才会出现,反复的CodeReview证明,这个类里所有的实现都不会因为多线程、多进程而产生问题。Sqlite3本身编译的时候也定义了THREADSAFE=1,也即多线程、多进程安全。

 

为了找到这个问题的原因,写了自动化测试代码,模拟了多进程、多线程同时修改、查询、建立表格等操作,均未发现问题。

 

最后各种打Log,才发现问题的原因在ensureDB()中的这个判断中:

这是仅有的在多进程、多线程下会出问题的地方。流程如下:

1. 安装包调用existTable(),返回false,准备调用createTable()。

2. CPU切换到主程序,主程序调用existTable(),返回false,准备调用createTable()。

3. CPU切换到安装包,安装包调用createTable(),返回true,进而ensureDB()返回true。

4. CPU切换到主程序,主程序调用createTable(),返回false,因为该表格在安装包中已经创建,于是createTable()中对sqlite3_exec(“create table”)的调用返回了SQLITE_ERROR,导致ensureDB()返回false,进而setValue等失败。

 

问题原因已经找到,目前没有完美的解决办法,已使用的解决办法如下:

 

8.2 更新:

该问题发现有更完美的解决方案:
SQLITE3支持CREATE TABLE IF NOT EXISTS语句,允许只在表不存在的时候,才进行创建,省去用C++代码进行判断的过程。CreateTable的定义见:
http://www.sqlite.org/lang_createtable.html

 

Libcef的那些坑

前段时间,公司项目里需要嵌入浏览器内核,由于IE的各种问题,于是采用了Libcef

首先感谢一下Chrome所有相关的开发者,为大家提供了如此方便高速的内核使用。其次感谢Libcef的作者,大大降低了使用Chromium内核的难度,起码编译这一大难关不需要去闯了。

然后我要开始数落Libcef的各种坑了,我使用的是Libcef3。

Continue reading