最近这些天,我一有时间就捣鼓 .rc
。用 git
管理过 .rc
文件的小伙伴儿应该都知道,.rc
文件会被 git
默认当作二进制文件来管理。每次合并代码的时候,只要涉及到 .rc
文件的变更,很大概率会报冲突,而且工具不能很好的解决,只能手动解决。为了解决这个问题,我想到了两个方案:
这两个方案相互之间没有任何冲突,所以这次折腾的时候,这两个方案是同时进行的。本以为没什么值得写的,没想到收获了意外惊喜,于是有了本篇总结。
按照微软官方文档 TN035: Using Multiple Resource Files and Header Files with Visual C++ 的指示,很快就拆分好了。满心欢喜的准备编译运行,验收成果。
没想到……
编译很快结束了,不过 vs
报告了下图所示的编译错误:
乍一看有一点懵,不过仔细看文件内容后知道怎么回事了。原来这是一个“老朋友”了,之前遇到过。不是什么大问题,只需要在后面多加一个空行就行了。
温馨提示:
如果在 resource.h
中包含自定义的头文件时,也需要在被包含的头文件的末尾加一个空行。否则也会报错。
在末尾加好空行后,再次编译,成功,正常运行。
解决了在同一工程中使用多个 .rc
的问题,下一个问题是让 .git
不再把 .rc
文件当成二进制文件来管理。默认情况下,.rc
文件会被当成 binary file
来管理的,当 .rc
中有差异的时候,在命令行中执行 git diff
命令,不能显示出有意义的信息。
按照 gitattribtes帮助文档 中的说明,我在项目根目录建立了 .gitattributes
文件,把 .rc
和 .rc2
文件都当成 UTF-16
来管理,这样再冲突的时候就可以比较差异了。
说明:
因为现有项目中的 .rc
文件都被当成了二进制文件,所以我在 .gitattributes
中末尾的位置把旧的 .rc
和 .rc2
文件强制设置为了 binary
。
设置好 .gitattributes
文件后,手动修改 .rc
文件内容,然后执行 git diff
查看差异。结果如下图,这次显示的差异简直完美。以说明新增加的设置是生效的。
本以为本次折腾就这么顺利的结束了,可以打扫战场,编写操作文档,收工了。
没想到……
撤销完变更后,编译,居然出现了下图中的错误:
这是什么错误?一脸懵逼,难道上面哪个地方多写了 #endif
导致不匹配了?赶紧把改动过的文件都检查一遍,尤其是刚刚改动过的文件。
每个文件都反反复复看了好几遍,什么问题都没看出来。#if
和 #endif
都是成对儿的。这可如何是好,网上搜索 error RC1020
,没有一条能解决我遇到的问题。
看了很长时间也没发现哪不对,于是我开始玄学了。
难道 #include
的头文件路径不对?调整包含路径,依然报错。
难道不能在 .rc
中包含头文件?不应该啊,默认生成的 .rc
就包含了 resource.h
啊。删除,可想而知,依然报错。
就这样排除了很多种“可能性”,试了很多方案,都没有用。但是得到了一个结论:只要包含这个 .rc
文件,编译就有问题。要不是刚开始在拆分完 .rc
后已经成功运行程序了,我都有些怀疑是不是不支持在同一个工程中使用多个 .rc
了。
实在不知道是哪里出问题了,于是起来接了杯水,在回座位的路上,脑子里突然蹦出来一个想法:双击打开有问题的 .rc
文件看看能不能看出点什么门道来。如下图:
嗯?怎么是空的?我的对话框去哪了?(内心一阵窃喜)赶紧打开一个正常的 .rc
文件看看,如下图:
该有的都有。手动把正常显示的对话框的内容拷贝到有问题的 .rc
中,看看能否打开,发现居然还是打不开!!!炸了,赶紧通过 beyond compare
对比看看。
虽然提示 Difference not found
,但是如果仔细看的话,两边的编码是不同的。为了进一步确认,于是打开 Hex Editor
查看文件头,果然不一样。![hex-compare-bom-header]
正常的 .rc
文件是按小端存储的—— FF FE
,也就是UTF16 LE with Bom
。有问题的 .rc
文件是按大端存储的—— FE FF
,也就是 UTF16 BE With Bom
。
知道了原因,于是赶紧修改有问题的 .rc
文件为小端模式.
警告:
不能直接修改文件头,否则打开时文件内容不对。可以使用 notepad.exe 打开有问题的 .rc 文件,然后另存为的时候选 UTF16 LE
即可。
再次双击打开发现可以正常打开了,并且编译也没问题了。特地贴一张编译通过的截图,我太难了。
本以为编译都通过了,应该就万事大吉了吧,没想到运行的时候直接崩溃了。我也要崩溃了。
说明:
因为我设置了 windbg
为 JIT
调试器,所以程序崩溃后直接到 windbg
中了。
在 vs
中按 F10
启动,单步跟踪,很快就发现是获取对话框的时候失败了。
看来又是 .rc
问题,难道生成的程序的资源段有问题了?使用 CFF Explorer
打开程序查看资源段,如下图:
果然,程序资源段中没有任何对话框,难怪查找对话框的时候找不到。看来跟刚才的 .rc
是一个问题,查看对应的 .rc
文件的文件编码,果然是一样的问题。修改文件编码,然后重新生成,启动后终于正常了。
这次的折腾真是一波三折,有点意思。几个关键点总结如下:
虽然问题解决了,但是为什么 .rc
文件的编码变了?而且还变错了。会是 git
的 bug
吗?
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2021-9-5 21:56
被编程难编辑
,原因: