首页
社区
课程
招聘
[原创]记一次曲折的多资源文件拆分折腾过程
发表于: 2021-9-5 21:49 7069

[原创]记一次曲折的多资源文件拆分折腾过程

2021-9-5 21:49
7069

最近这些天,我一有时间就捣鼓 .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 即可。

再次双击打开发现可以正常打开了,并且编译也没问题了。特地贴一张编译通过的截图,我太难了。

本以为编译都通过了,应该就万事大吉了吧,没想到运行的时候直接崩溃了。我也要崩溃了。

说明:
因为我设置了 windbgJIT 调试器,所以程序崩溃后直接到 windbg 中了。

vs 中按 F10 启动,单步跟踪,很快就发现是获取对话框的时候失败了。

看来又是 .rc 问题,难道生成的程序的资源段有问题了?使用 CFF Explorer 打开程序查看资源段,如下图:

果然,程序资源段中没有任何对话框,难怪查找对话框的时候找不到。看来跟刚才的 .rc 是一个问题,查看对应的 .rc 文件的文件编码,果然是一样的问题。修改文件编码,然后重新生成,启动后终于正常了。

这次的折腾真是一波三折,有点意思。几个关键点总结如下:

虽然问题解决了,但是为什么 .rc 文件的编码变了?而且还变错了。会是 gitbug 吗?


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-9-5 21:56 被编程难编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 3700
活跃值: (4091)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
期待后续。
2021-9-6 07:38
0
雪    币: 2
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
有时候程序的错误也很难讲是什么问题,我之前写代码的时候就出现vs会跳过一个语句,只要换行就能正常执行,这个问题现在我也没想明白。
2024-2-26 09:01
0
游客
登录 | 注册 方可回帖
返回
//