1 Star 0 Fork 0

aiminick / deepin-wine-guide

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 12.24 KB
一键复制 编辑 原始数据 按行查看 历史
Wei xie 提交于 2021-03-11 09:56 . feat: FAQ添加子标题

wine介绍

Wine是一个在X86、X86-64上容许类Unix操作系统在X Window System下运行Microsoft Windows程序的软件。

Wine全名为 "Wine Is Not an Emulator",即Wine不是模拟器。虽然Wine有另一个非官方名称,"Windows Emulator",即Windows模拟器。Wine的正确名称是"Wine",不是全大写、全小写或大小写混合。

Wine不是模拟器,而是用兼容模式调用DLLs以运行Windows程序,Wine虽然是为Linux而制,但亦能支持FreeBSD 与 Solaris-x86。

有兴趣的同学可以参阅wine wiki

deepin-wine 版本介绍

deepin-wine目前维护了如下几个版本

deepin-wine

安装命令:

sudo apt install deepin-wine

运行命令:deepin-wine

deepin-wine5

安装命令:

sudo apt install deepin-wine5

运行命令:deepin-wine5

deepin-wine5-stable

deepin-wine5-stable是集成到应用的包里面,最新的UOS版本运行了商店安装的wine应用之后会释放。

运行命令: ~/.deepinwine/deepin-wine5-stable/bin/wine

文章中运行命令都用deepin-wine表示,如果要用其他版本改成对应版本的命令。

常用wine命令:

容器 + deepin-wine winecfg
容器 + deepin-wine regedit
容器 + deepin-wine cmd
...

更多的可以查看wine源码目录的programs下的插件

可以查看deepin-wine --help 了解参数传递规则

$ deepin-wine --help
Usage: wine PROGRAM [ARGUMENTS...]   Run the specified program
       wine --help                   Display this help and exit
       wine --version                Output version information and exit

如何通过deepin-wine运行Windows程序

WINEPREFIX=~/.deepinwine/Deepin-QQ/ deepin-wine ~/.deepinwine/Deepin-QQ/drive_c/Program\ Files/Tencent/QQ/Bin/QQ.exe

WINEPREFIX=~/.deepinwine/Deepin-QQ/: 指定容器目录

deepin-wine: 指定的wine 可以替换 deepin-wine5/deepin-wine5-stable等不同版本wine

~/.deepinwine/Deepin-QQ/drive_c/Program\ Files/Tencent/QQ/Bin/QQ.exe: 要运行的应用二进制可执行文件

后面描述 容器 + 都可以理解为WINEPREFIX=~/.deepinwine/Deepin-Test/这种形式的目录

wine配置

容器配置参考: config

wine日志

调试通道 (debug channel)

wine定义了调试通道的概念来分类日志,将日志的记录和实际的输出分离,无需重新编译,就能灵活控制日志输出。

  • wine把日志分成了4个级别,从高到低依次是:fixme/err/warn/trace,对应的提供了4个宏来输出不同级别的日志到调试通道:FIXME/WARN/ERR/TRACE
  • 每个调试通道有一个唯一的名字, 长度不超过14个有效字符, 一般一个模块至少定义了一个调试通道,比如 gdi32.dll模块,有一个名称叫gdi的调试通道.
  • 复杂的模块,为了细分日志定义了多个调试通道,比如 gdi32.dll模块,还有定义clipping,region,font,bitmap,print,bitblt等调试通道
  • 调试通道在代码里面来看实际是一个__wine_debug_channel 的结构体,刚好16个字节,非常符合 unix哲学的简单原则:
struct __wine_debug_channel
{
    unsigned char flags;
    char name[15];
};
  • 日志一次只发送给一个调试通道.
  • 代码里面如何增加一个新的调试通道:
    1. 包含 include/wine/debug.h
    2. 然后用WINE_DEFAULT_DEBUG_CHANNELWINE_DECLARE_DEBUG_CHANNEL宏来声明
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(test)
WINE_DECLARE_DEBUG_CHANNEL(mytest)

运行前开启调试通道

这样的格式定义环境变量:

WINEDEBUG=[class][+/-]channel[,[class2][+/-]channel2]

其中: * class是fixme,err,warn,trace这4个日志级别的一个单词,如果没有指定就开关所有的日志级别.

  • channel就是要开关的调试通道的名称,all代表所有的通道.
  • +就是开启指定调试通道的对应的日志级别.
  • -就是关闭指定调试通道的对应的日志级别.

举例:

WINEDEBUG=warn+all
WINEDEBUG=warn+dll,+heap
WINEDEBUG=fixme-all,warn+cursor,+relay

仅标记作用的调试通道

  • pid: 在每个日志的前面插入当前进程的ID号,格式: %04x
  • tid: 在每个日志的前面插入当前线程的ID号,格式: %04x
  • timestamp: 在每个日志的前面插入时间戳, 相对系统启动的时间, 单位秒,保留3位小数

特殊的高级的调试通道

  • seh: 记录所有的异常情况,快速定位程序崩溃地址。
0009:trace:seh:raise_exception code=c00002b5 flags=0 addr=0xc4194be ip=0c4194be tid=0009
0009:trace:seh:raise_exception  info[0]=00000000
0009:trace:seh:raise_exception  eax=00000006 ebx=0b6f4f58 ecx=08b44020 edx=0033d15c esi=0dfde520 edi=0df80020
0009:trace:seh:raise_exception  ebp=0033d0d0 esp=0033d0c0 cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00210206
  • relay: 无需修改代码,记录程序调用wine实现的所有API的详细参数和返回值,注意:此通道谨慎使用,开启它会输出大量日志,一般情况不建议使用,实在没有头绪时可以考虑使用。
...
0017:Call KERNEL32.CreateFileA(7ea8e936 "CONIN$",c0000000,00000003,00000000,00000003,00000000,00000000) ret=7ea323fd
0017:Ret  KERNEL32.CreateFileA() retval=00000023 ret=7ea323fd
...

winetricks介绍

如果 winecfg (WINE 的配置工具)是一把螺丝刀,那么 winetricks 就是一个钻床。它们各有特长,但是 winetricks 真的是一个强大的多的工具。实际上,它甚至可以启动 winecfg。

winecfg 让你可以改变 WINE 本身的设置,而 winetricks 则可以让你改造实际的 Windows 层,它可以让你安装 Windows 重要的系统组件,比如 .dll 文件和系统字体,还可以允许你修改 Windows 注册表的信息。它还有任务管理器、卸载工具和文件浏览器。

尽管 winetricks 可以做以上这些工作,但是大部分时间我们用到的功能也就是管理 dll 文件和Windows组件。

为什么要使用winetricks安装?比如你想安装riched20,但riched20它有很多依赖,你不想一个一个去找到它对应版本的依赖逐个安装时,此时只需要执行winetricks riched20 即可。

安装

sudo apt install winetricks

使用winetricks安装

容器 + winetricks xxx

或者直接使用winetricks的UI操作安装:

直接执行winetricks命令后弹出操作UI,根据提示选择需要安装,最后确定,等待安装完成即可。

winetricks

FAQ

输入框不能输入问题

输入框的实现基本离不开riched20这个模块,目前wine上游的riched20模块还存在很多问题,基本上遇到此类问题直接替换riched20都能解决,可以使用winetricks安装riched20后,在winecfg中配置riehed20为"原装先于内建"即可。

容器 + winetricks riched20
容器 + deepin-wine5-stable winecfg

image-2

缺失MFC问题

wine version: 5.0
0009:err:module:import_dll Library MFC42.dll (which is needed by L"c:\\graphedt.exe") not found
0009:err:module:LdrInitializeThunk Importing dlls for L"c:\\graphedt.exe" failed, status c0000135
容器 + winetricks mfc42

由于我这里的winetricks版本中没有独立的mfc42这个dll,提示安装失败,这种情况也是经常遇到,那么可以选择使用手动方案:

我们可以去网上下载MFC42.dll,也可以去windows虚拟机windows/system32目录下拷贝,记得下载版本一定是要32位,之后拷贝到容器的windows/system32目录或应用可执行文件同目录即可。

缺失vcrun*

wine: configuration in L"/home/chaol/.deepinwine/Deepin-TEST" has been updated.
0009:err:module:import_dll Library mfc140u.dll (which is needed by L"C:\\hellow.exe") not found
0009:err:module:LdrInitializeThunk Importing dlls for L"C:\\hellow.exe" failed, status c0000135

wine: configuration in L"/home/chaol/.deepinwine/Deepin-TEST" has been updated.
0009:err:module:import_dll Library vcruntime140.dll (which is needed by L"C:\\hellow.exe") not found
0009:err:module:LdrInitializeThunk Importing dlls for L"C:\\hellow.exe" failed, status c0000135

可以先查找它们属于哪个vcrun

image-20210305093206579

mfc140u.dll也属于vcrun的运行时库,都需要安装vcrun2015

容器 + winetricks vcrun2015

image-20210305093206579

缺失.Net

wine version: 5.0
0009:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.6.1" not implemented
0009:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.6.1" not implemented
0009:err:mscoree:CLRRuntimeInfo_GetRuntimeHost Wine Mono is not installed

wine这边提示的是需要安装mono,但实际上我们只需安装.net效果是一样的。

容器 + winetricks dotnet46

字体乱码问题

主要体现ui上的字体显示乱码,看到乱码问题,一般有以下几个方向

1.字体文件缺失

最直接的方法:把windows系统下的windows/Fonts/* 的字体文件全部拷贝到容器的windows/Fonts/目录,然后再运行应用看是否能正常显示,如果正常显示,那么说明它缺少了windows下面的一个字体库,这时我们可以采用二分法,逐次删除容器目录下的字体文件,找到最终能显示字体的文件为止。

2.找不到对应字体字号

这类问题定位较为复杂,字体明明已经找到,但显示依然乱码,这是因为这个字体库中没有应用中使用的字号,这种情况较为少见,但也是存在的,之前就遇到同一个字体库,但是版本有少许差别,一个能正常显示,一个显示乱码,我们还是能从日志中分析出原因。一般这类问题一般是绘制字体时出错,所以我们需要开启跟绘制相关的通道,常用的几个绘制通道是gdi,gdiplus,opengl,d3d等,字体还是gdi为主,我们可以观察freetype_SelectFont,freetype_GetGlyphOutline,freetype_GetFontData, nulldrv_ExtTextOut等这些跟字体绘制相关的api,多在这些api中增加自己的日志信息以便更容易分析问题原因。

注意:由于版权问题,wine尽量不使用字体库方式,找到缺失字体后在user.reg注册表加入对应字体,有版权问题的不要拷贝字体文件,示例如下:

容器 + deepin-wine regedit /S [font.reg](./source/font.reg)

COM组件未注册

wine version: 5.0
0009:fixme:nls:GetThreadPreferredUILanguages 00000038, 0x32fad0, 0x32fae0 0x32fad4
0009:fixme:nls:get_dummy_preferred_ui_language (0x38 0x32fad0 0x32fae0 0x32fad4) returning a dummy value (current locale)
0009:fixme:process:RegisterApplicationRestart (L" /RestartByRestartManager:35EA96D3-726B-464a-B910-2FA273ED5A0F",0)
regsvr32: 无法加载 DLL "/sC:\ONLINEHB1.0\MSCHRT20.OCX"
容器 + deepin-wine regsvr32 C:\\ONLINEHB1.0\\MSCHRT20.OCX

/s是regsvr32的参数,可以查阅msdn文档查看详细介绍,这里错误信息可以看到它与com路径中间没有空格,这是wine的一个错误,我们在注册时可以根据情况忽略或者把空格加上。

wine version: 5.0
0009:err:ole:CoGetClassObject class {9165c9f3-ce90-4b41-8741-9243d0f39049} not registered
0009:err:ole:CoGetClassObject class {9165c9f3-ce90-4b41-8741-9243d0f39049} not registered
0009:err:ole:create_server class {9165c9f3-ce90-4b41-8741-9243d0f39049} not registered
0009:fixme:ole:CoGetClassObject CLSCTX_REMOTE_SERVER not supported

我们可以先在windows下安装好应用可以正常运行后,在注册表中搜索“9165c9f3-ce90-4b41-8741-9243d0f39049“, 找到com的文件名,然后再在容器注册此comimage-20210305174759372

容器 + deepin-wine5-stable regsvr32 C:\\AxGUI.ocx
1
https://gitee.com/aiminick/deepin-wine-guide.git
git@gitee.com:aiminick/deepin-wine-guide.git
aiminick
deepin-wine-guide
deepin-wine-guide
master

搜索帮助