编译支持Log功能的Unicode NSIS
2009-06-25 20:36
344 查看
对于开发多语言版本的安装包来说,使用Unicode NSIS就成了一个比较自然的选择。然而Unicode Nsis属于官方NSIS的衍生版,开发进度势必落后于官方的NSIS,主要由Jim一个人进行维护。现在官方最新版本是2.45,而Unicode版还停留在2.42。
用过NSIS的都知道,NSIS的默认方式是手写卸载脚本的。如果使用了支持LOG功能的特殊版NSIS(也是官方的)。使用这个版本的NSIS生成的安装包可以在安装过程中生成日志文件,再加上网友提供的现成脚本,就可以比较方便地实现用日志文件进行卸载的功能。实现方式可以参考NSIS的基本结构一文。
然而,Unicode NSIS的作者没有提供支持LOG功能的NSIS的下载。而只提供了源代码下载。这样我们就不得不自己重新编译NSIS。编译过程很简单,加上一个NSIS_CONFIG_LOG编译参数就可以。但是如果问题这么简单就没有必要写个文章专门介绍一下了。
问题就在于,用自己编译出来的NSIS生成的安装包生成的LOG文件有错误!什么错误呢?在网上没有搜到任何线索,只能自己分析一下LOG文件,自己找错误了。(昨天给Jim发了邮件,不过没有时间等他的回复了)
查看了Unicode NSIS的相关源代码和《Windows核心编程》,发现最有可能出问题的就是WriteFile函数的问题。相关源代码如下。
[/code]
Unicode NSIS生成的所有字符串都是Unicode编码的,写到这个文件里的字符串也是。那么上面的代码有两个问题。
1. 作者在创建这个文件的时候,没有声明这个文件是Unicode文件,使得记事本在打开文件时,以ANSI编码打开,从而产生错误。这个声明就是Byte Order Mark,只是针对Windows平台的部分Unicode文件有这个约束。(比如VS就可以选择是否在源代码文件中加入BOM。)
2. WriteFile时,第三个参数不正确。第三个参数的单位是字节,但是mystrlen函数返回的是log_text的字符数。而Unicode的一个字符有sizeof(TCHAR)个字节。所以实际写入文件中的字符串,只是log_text的前sizeof(TCHAR)分之一。
好了,问题找到了,着手修改源代码吧。先加上BOM,再把第三个参数乘以sizeof(TCHAR)。编译很顺利地完成。生成的LOG文件也是完整的了并能用记事本打开了。
但是,卸载功能无效。把生成的Unicode编码的Log文件另存为ANSI编码的。能卸载了~~~~看来这个Unicode NSIS的卸载包不是很完美啊。想必要让Uninstaller支持Unicode又要改不少代码。一想还有另一种可能是Uninstaller不认识BOM,毕竟NSIS是跨平台的,但是如果记事本不可读也是不能接受的。后来试了一下,果然不能有BOM。把BOM去掉,Uninstaller就正常工作了。
最终代码修改如下:
[/code]
然后用下面的指令Build一下,
scons UNICODE=yes NSIS_CONFIG_LOG=yes SKIPUTILS=”NSIS Menu” PREFIX=”Your Install Folder” install
支持Log的Unicode版NSIS就生成好了。
另外附上自己编译好的补丁,覆盖现有安装即可。
更新:
这时生成的Log文件是Unicode编码,而FileRead指令是不能正确读取Unicode文件的。这样就导致Uninstall By Log功能无法正常运行。
解决方法也很简单,把读取Unicode文件的FileRead指令替换成Unicode NSIS所特有的FileReadUTF16LE就可以了。
用过NSIS的都知道,NSIS的默认方式是手写卸载脚本的。如果使用了支持LOG功能的特殊版NSIS(也是官方的)。使用这个版本的NSIS生成的安装包可以在安装过程中生成日志文件,再加上网友提供的现成脚本,就可以比较方便地实现用日志文件进行卸载的功能。实现方式可以参考NSIS的基本结构一文。
然而,Unicode NSIS的作者没有提供支持LOG功能的NSIS的下载。而只提供了源代码下载。这样我们就不得不自己重新编译NSIS。编译过程很简单,加上一个NSIS_CONFIG_LOG编译参数就可以。但是如果问题这么简单就没有必要写个文章专门介绍一下了。
问题就在于,用自己编译出来的NSIS生成的安装包生成的LOG文件有错误!什么错误呢?在网上没有搜到任何线索,只能自己分析一下LOG文件,自己找错误了。(昨天给Jim发了邮件,不过没有时间等他的回复了)
查看了Unicode NSIS的相关源代码和《Windows核心编程》,发现最有可能出问题的就是WriteFile函数的问题。相关源代码如下。
[code]if (g_log_file[0] && fp == INVALID_HANDLE_VALUE)
{
fp = myOpenFile(g_log_file, GENERIC_WRITE, OPEN_ALWAYS);
if (fp != INVALID_HANDLE_VALUE)
SetFilePointer(fp, 0, NULL, FILE_END);
}
if (fp != INVALID_HANDLE_VALUE)
{
DWORD d;
mystrcat(log_text,_T("\r\n"));
WriteFile(fp,log_text,mystrlen(log_text),&d,NULL);
}
[/code]
Unicode NSIS生成的所有字符串都是Unicode编码的,写到这个文件里的字符串也是。那么上面的代码有两个问题。
1. 作者在创建这个文件的时候,没有声明这个文件是Unicode文件,使得记事本在打开文件时,以ANSI编码打开,从而产生错误。这个声明就是Byte Order Mark,只是针对Windows平台的部分Unicode文件有这个约束。(比如VS就可以选择是否在源代码文件中加入BOM。)
2. WriteFile时,第三个参数不正确。第三个参数的单位是字节,但是mystrlen函数返回的是log_text的字符数。而Unicode的一个字符有sizeof(TCHAR)个字节。所以实际写入文件中的字符串,只是log_text的前sizeof(TCHAR)分之一。
好了,问题找到了,着手修改源代码吧。先加上BOM,再把第三个参数乘以sizeof(TCHAR)。编译很顺利地完成。生成的LOG文件也是完整的了并能用记事本打开了。
但是,卸载功能无效。把生成的Unicode编码的Log文件另存为ANSI编码的。能卸载了~~~~看来这个Unicode NSIS的卸载包不是很完美啊。想必要让Uninstaller支持Unicode又要改不少代码。一想还有另一种可能是Uninstaller不认识BOM,毕竟NSIS是跨平台的,但是如果记事本不可读也是不能接受的。后来试了一下,果然不能有BOM。把BOM去掉,Uninstaller就正常工作了。
最终代码修改如下:
[code]if (fp != INVALID_HANDLE_VALUE)
{
DWORD d;
mystrcat(log_text, _T("\r\n"));
#ifdef UNICODE
WriteFile(fp, log_text, mystrlen(log_text) * sizeof(TCHAR), &d, NULL);
#else
WriteFile(fp, log_text, mystrlen(log_text), &d, NULL);
#endif
}
[/code]
然后用下面的指令Build一下,
scons UNICODE=yes NSIS_CONFIG_LOG=yes SKIPUTILS=”NSIS Menu” PREFIX=”Your Install Folder” install
支持Log的Unicode版NSIS就生成好了。
另外附上自己编译好的补丁,覆盖现有安装即可。
更新:
这时生成的Log文件是Unicode编码,而FileRead指令是不能正确读取Unicode文件的。这样就导致Uninstall By Log功能无法正常运行。
解决方法也很简单,把读取Unicode文件的FileRead指令替换成Unicode NSIS所特有的FileReadUTF16LE就可以了。
相关文章推荐
- 编译openwrt支持USB自动mount功能
- 具有编译功能支持无限大数计算器的实现
- 编译内核使tilera支持网桥和netfilter功能
- Python高级 -- 12 mini_frame框架添加路由、路由支持正则、Log日志功能
- InstallShield 2012 Spring新功能试用(17): Suite/Advanced UI 和 Advanced UI安装程序支持命令行Log参数
- 支持浮点运算功能的交叉编译工具链的制作
- 本地编译全志R系列的步骤7(Ubuntu 17.04非长期支持版本)原始LOG未整理
- [javascript,js]Firefox,Netscape,IE8支持的log功能
- Ubuntu 16.04下安装以太坊编译环境以及设置合约功能(支持geth 1.6以及solc 0.4.16版本以上)
- squid 编译支持 ESI 功能
- 功能不错!IE11支持基于网页的文件编辑
- linux下编译postfix时,使其支持mysql,ldap,sasl,ssl的脚本
- LAMP 全功能编译安装 for CentOS6.3笔记
- 为什么C++编译器不支持模板头文件和实现代码分离的编译
- VS2015使用opencv3.2.0版本,支持X64位编译的配置
- 添加现有项目来重用代码。使用编译功能查找错误。
- 很多C编译不支持bool型,导致出现false和true未定义
- Linux Mint下编译安装支持SPDY协议的Wireshark
- win8支持多屏幕的功能如何设置才可以使用
- 重新编译spark源码,使CDH支持spark sql