本文记述解决信创系统显示问题过程经历,描述遇到的各种问题以及解决方法。
问题描述
测试反馈,在信创系统上,部分界面字体显示异常,表现为内容越界、文字区域显示为小空格,如下图所示:
初步分析是字体原因,具体情况需要更进一步分析。
问题复现
测试团队的信创测试环境有UOS
和Kylin
两个系统,为了不干扰测试团队的测试,选择在本地虚拟机上搭建相同信创环境。
-
安装信创系统
安装UOS
系统很顺利,安装Kylin
遇到问题。载入镜像之后,虚拟机一直停留在光标闪烁界面,无法进入后续安装流程。经过查阅资料,猜测可能是Vmware
版本太低,本地Vmware
是版本是12.0.2,准备升级虚拟机 -
安装新版虚拟机之前,需要删除旧版本。通过控制版本删除旧版本失败,提示需要什么
msi
才能卸载,原始安装包早就删掉,无法通过控制面板删除,无奈之下,只好手动删除Vmware安装目录加清理注册表。 -
因为本机是
Win7
,支持Win7
的Vmware
最高版本是VMware-workstation-full-15.5.6-16341506.exe
,于是哼哧哼哧去下载,在安装过程中,提示需要tools-linux.msi
文件,这就很奇怪,在网上找了半天,下载了多个版本的vmware-tools
在里面都没找到tools-linux.msi
,为什么安装时还要依赖其他文件呢?又在网上搜索解决方案,最后通过下载Windows官方卸载工具 MicrosoftProgram_Install_and_Uninstall.meta,把涉及到Vmware
的组件都卸载,然后清理注册表,重启电脑后再次安装新版Vmware
,终于安装成功,Kylin
系统也顺利安装。 -
启动程序。因为信创环境是基于Linux开发的,exe格式的不能直接运行。系统自带的
wine
是64位,它无法启动32位程序。要么编译64位程序,要么运行32位的wine。- 尝试编译64位程序。发现相关依赖的组件不支持64位编译,放弃
- 尝试运行32位wine。在网上搜索一圈,编译32位的wine,安装流程来走,遇到各种各样的问题,最终放弃。
-
回想起测试人员是运行原生包来测试,而我这边是通过wine启动运行,这两者是不是存在区别呢?通过测试对比发现,果然存在区别,同样的操作,在原生包启动和通过wine启动,表现不一样。
- 转换思路,要么将开发环境的exe打包成新创环境的格式,要么通过第三方启动器运行。
方法1: 自己打包。咨询了运维同事,将程序打包成deb
需要知道各种依赖的情况,较为复杂,不走这条路
方法2:通过第三方运行期运行。经过调研得知,在UOS
系统中,可通过应用商店下载 wine运行器,运行界面如下图:
在
Kylin
系统上,可通过CrossOver
(功能和wine
类似)运行,运行界面如下图:万事俱备,只欠东风。
- 转换思路,要么将开发环境的exe打包成新创环境的格式,要么通过第三方启动器运行。
预备知识
-
Windows字体基础概念以及绘制方法
-
GDI+在绘制文字时,遇到不支持的字符会如何处理?
GDI+
的DrawString
包含字体回滚机制,当所选字体无法支持显示字符时,会选择其他系统字体来显示,当没有font fallback 发生时,会显示空白方框。 -
Wine介绍,它将Windows API调用动态翻译成POSIX调用。这是Wine使用手册,
Wine
分为32位和64位,32位只能启动32位程序,64位只能启动64位程序。还有一种支持WoW64机制
的Wine
,运行同时运行32位和64位程序,具体可参考wine实用经验教程 -
通过
wine运行器
启动和wine ./xxx.exe
启动,两者展示效果不同。通过对比发现是启动Wine的命令行有区别。- 显示正常的 WINEPREFIX=~/xx wine xx.exe
- 显示不正常的 wine xx.exe
经过搜索和验证,发现是不同容器中的字体不同导致的。
-
wine
命令行启动参数介绍- WINEARCH=winxx,指定Windows架构,可设置为Win32或者Win64.
- WINEPREFIX=路径 指定程序运行容器环境,
wine
使用虚拟C驱动器,默认路径为 ~/.wine,程序启动后,会在 WINEPREFIX 路径下创建 drive_c/ 等文件夹和文件。要安装一个windows
程序,一般在设置好WINEPREFIX
和WINARCH
后,再运行程序。
-
winetricks
方便用户配置wine环境,可安装基础DLL
、运行库之类的。通过WINEPREFIX=路径 winecfg
来配置特定路径的容器。一般来说,为每个windows
程序建立独立容器,这样各类兼容包、字体和调用的dll都不会相互影响,移植和删除更灵活。
解决尝试
考虑显示异常可能是字体问题后,有如下解决思路。
思路一:当遇到字体不可用时,在本机找另一个可用的字体
思路二:手动安装字体
思路一细化流程:
1. 找出本机当前安装的所有字体
2. 用每种字体都输出相同信息,查看是否显示异常。
3. 找到判断字体显示异常的依据,并将显示正常的字体保存起来。
4. 使用配置字体时,如果发现字体不可用,就从3)种的字体集合中取1个。
结论1:相同内容,会因为输出字体的不同,显示宽度和高度有所区别。
结论2:枚举得到的本机的所有字体,也存在部分字体显示不正常情况
结论3:当所选字体无法显示特定字符时,不同字体表现不一样。有的表现为输出空白小方块,有的显示乱码,还有的中文输出空白小方块,数字正确显示。
结论4:通过对比显示正常和不正常的字体信息,没找到区分字体显示正确与否的依据。最初找到字体的lfCharSet属性,相关定义如下:
显示正确的值为0,显示错误的值为2。这个区别在Windows系统是可行的,但在信创系统上不行。
尝试通过函数 GetFontLanguageInfo 获得字体信息,用其返回值来区分,测试结果让人失望。
此路不通。
思路二细化流程:
1. 通过wine命令行启动程序,安装字体很麻烦。因此,选择第三方运行器启动。
2. 在本地构建带调试信息的Release
版本程序,通过 beyongcompare文件夹同步
同步到信创共享目录,因为共享目录读写权限的问题,无法新建文件,需要再从信创共享目录拷贝到信创本地目录,可通过 rsync
或者 beyongcompare文件夹同步
实现。
3. 在启动之前,通过第三方运行器安装字体,经过对比验证,发现安装字体的实质就是将下载的字体文件拷贝到到运行容器C
盘的Windows\Fonts
目录中。
最终,字体显示问题,通过安装缺失字体的方式解决。
小结
此问题花费了将近1个星期,在本地将信创验证环境搭建好,为后续相关问题的解决打下基础,在此小结。
- 基础环境搭建
Win7
系统最高可安装VMware 15.5.6
.如果是Win10
或Win11
,可以安装更高版本的VMware
- 信创系统安装。安装
UOS
家庭版,安装Kylin
社区版,不要乱升级内核和系统,够用就行。
- 调试环境搭建
- 待调试程序构建为
Release
版本,增加调试信息 - 安装
samba
服务,以便从window
访问到信创共享目录 - 使用
BeyondCompare
的文件夹同步功能或者rsync
的增量拷贝功能同步程序 UOS
系统使用wine启动器
;Kylin
系统使用CrossOver
,不建议从源码编译32位的wine
,太繁琐且很难成功。- 字体问题,从第三方启动器下载字体,或者从本地
Windows
系统的Windows/Fonts
目录中拷贝所有字体
- 待调试程序构建为
- 调试手段
- 打印日志。在网络共享路径,会因权限问题打印失败,因此需要同步到信创本地再打印。为提高效率,可屏蔽不相关日志输出,给日志增加关键字,便于后续定位分析。
- 弹框提示。在关键路径上,可用弹框提示的方式来指示程序运行路径和状态信息。
- 系统配置文件要调整为对应环境的配置,不能用windows的环境配置跑在信创环境上。这一点坑了笔者很多时间。介绍下是如何区分不同系统的,方法很简单,在本地增加OSVersion配置项,发布打包时,Windows系统中填 Windows,UOS系