wine运行软件的排错和常见问题 您所在的位置:网站首页 百度网盘已崩溃 wine运行软件的排错和常见问题

wine运行软件的排错和常见问题

2024-07-16 13:41| 来源: 网络整理| 查看: 265

背景

wine的安装并不是这篇文章的主题,所以这里我们借用docker-wine来构建运行环境,避免啰哩啰嗦的事情

这个镜像包括了多种运行方式,我根据需要以daemon进行持久化运行

# tty是为了保持运行不退出 # 其他参数是为了通过x11来进行显示,以及软件目录 docker run -d \ --name wine \ --tty=true \ --hostname="$(hostname)" \ --env="DISPLAY" \ --volume="${XAUTHORITY:-${HOME}/.Xauthority}:/root/.Xauthority:ro" \ --volume="/tmp/.X11-unix:/tmp/.X11-unix:ro" \ -v /media/minecraft/Data/software/HALo/:/root/HALo \ scottyhardy/docker-wine \ bash # 进入到容器内部进行操作 docker exec -it wine bash

程序排错过程 首先配置一下wine

初始化运行wine需要进行一些初步的配置

# 这个参数代表了wine内部系统的根目录,更换之后相当于重新装了个新的wine的环境,默认是这个 export WINEPREFIX=$HOME/.wine # 64位还是32位,默认64 export WINEARCH=win64 # 配置wine的版本,建议设置 winecfg -v win10 排错开始,一些基本信息 # 我们直接运行程序,并根据程序的报错来确定问题所在 wine xxxx.exe

在我的运行过程中发现的是如下的log,其中会出现一大堆fixme相关的log,这个实际上是wine对于windows的日志系统的操作,这里大部分并没有进行实现(毕竟貌似没啥必要),所以会提示一些日志的方法没有实现,多数情况下可以忽略掉

wine: created the configuration directory '/root/.wine' 002c:fixme:actctx:parse_depend_manifests Could not find dependent assembly L"Microsoft.Windows.Common-Controls" (6.0.0.0) ... # 此处省路一大堆fixme 0078:fixme:nsi:ipv6_forward_enumerate_all not implemented 0078:fixme:nsi:ipv6_forward_enumerate_all not implemented 0078:fixme:nsi:ipv6_forward_enumerate_all not implemented 0078:fixme:nsi:ipv6_forward_enumerate_all not implemented [ERROR] FATAL UNHANDLED EXCEPTION: System.Runtime.InteropServices.COMException (0x80004005) at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR (System.Int32 errorCode) [0x0000a] in :0 at (wrapper cominterop) IWshRuntimeLibrary.IWshShortcut.set_IconLocation(string) at (wrapper cominterop-invoke) IWshRuntimeLibrary.IWshShortcut.set_IconLocation(string) at Mediinfo.WinForm.HIS.Main.Program.CreateShortcutOnDesktop () [0x00441] in WINEDEBUG变量

这里开始引入我们第一个非常重要的环境变量WINEDEBUG,该变量可以对wine的输出内容进行调整,例如这里我们不想显示fixme相关的内容,就可以设置一下,具体更详细的内容可以参考man wine中这一部分

export WINEDEBUG=fixme-all wine xxxx.exe # 或者这个方法临时进行设置环境变量 WINEDEBUG=fixme-all wine xxxx.exe

常用的几个参数是:

+relay,会把每一个函数的调用打印出来,会产生巨大的log同时极大的减慢程序的运行速度 +module,通常建议设置这个,用来寻找dll的问题很方便 # 根据以上建议,我们在调试的时候建议 export WINEDEBUG=fixme-all,+module # 平时运行建议 export WINEDEBUG=fixme-all 缺失的函数dll

好了,现在回到我们的出问题的部分,可以看到log最后面是打印出来了

[ERROR] FATAL UNHANDLED EXCEPTION: System.Runtime.InteropServices.COMException (0x80004005) at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR (System.Int32 errorCode) [0x0000a] in :0 at (wrapper cominterop) IWshRuntimeLibrary.IWshShortcut.set_IconLocation(string) at (wrapper cominterop-invoke) IWshRuntimeLibrary.IWshShortcut.set_IconLocation(string) at Mediinfo.WinForm.HIS.Main.Program.CreateShortcutOnDesktop () [0x00441] in

除开我们的程序本身自己的函数来讲,可以看到涉及到系统的函数是IWshRuntimeLibrary,网上进行寻找发现是属于wshom.ocx这个dll(?)的,当然另一种更靠谱的方法是github的镜像wine-mirror处进行寻找,函数具体实现可能和原dll中函数名称不一致,查找的时候要注意。

举例我这个函数是这个路径下找到的,可以看到具体的实现,这里提示是实现了程序所需要的函数,但是实际是运行不了的,不在这里继续探究了

接下来我们就要想办法解决这个缺失的dll了

用win自身的dll来替换

wine实现了大量的dll,但仍然有很多函数没有被实现,这个时候就可以考虑用非free的方式来让程序跑起来

通过winetricks这个工具可以很好的来进行安装各种非free的依赖

既然我们已经知道这个函数是属于wshom.ocx的,同时wsh是Windows Script Host,那我们就进行搜索和安装

winetricks dlls list | grep "wsh \| Script \| Host" #msscript MS Windows Script Control (Microsoft, 2004) [downloadable] #wsh57 MS Windows Script Host 5.7 (Microsoft, 2007) [downloadable] winetricks wsh57 # 加上-q安安静静的安装,别烦我 winetricks -q wsh57

这里我们要告诉wine,用winetricks的dll来替换wine自己的dll,方式有两种:

通过winecfg的库tab,输入wshom.ocx来进行添加设置native(windows)优先 通过命令的方式设置,本文章的方法 export WINEDLLOVERRIDES="wshom.ocx=n,b;这里继续写其他要替换的dll" # 有些dll需要注册一下才行 regsvr32 $WINEPREFIX/drive_c/windows/system32/wshom.ocx 更换32位

再次运行发现如果+module的话log太多,保存到文件里去寻找

export WINEDEBUG=fixme-all,+module wine xxxx.exe &> dbg.log

接下来的报错很复杂,最终我将其归结于64位的问题(毕竟System.Int32),之后整体切换到32位

[ERROR] FATAL UNHANDLED EXCEPTION: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Runtime.InteropServices.COMException at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR (System.Int32 errorCode) [0x0000a] in :0 ... at Mediinfo.WinForm.HIS.Main.Program.CreateShortcutOnDesktop () [0x002ea] in :0

切换32位很简单,只需要重新设置两个环境变量即可,之后就进入一个新的环境了,之后前面该做的事情再重复一遍即可

export WINEPREFIX=/root/.wine32 export WINEARCH=win32 winetricks -q wsh57 export WINEDLLOVERRIDES="wshom.ocx=n;" regsvr32 $WINEPREFIX/drive_c/windows/system32/wshom.ocx 中文问题

继续运行发现log中有?在,确认发现是中文问题,这个docker-wine并没有考虑中文问题,所以进行一下设置

[ERROR] FATAL UNHANDLED EXCEPTION: System.Runtime.InteropServices.COMException (0x8007007B): Unable to save shortcut "C:\users\root\Desktop\??HALO.lnk". at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR (System.Int32 errorCode) [0x0000a] in :0 at (wrapper cominterop) IWshRuntimeLibrary.IWshShortcut.Save() at (wrapper cominterop-invoke) IWshRuntimeLibrary.IWshShortcut.Save() at Mediinfo.WinForm.HIS.Main.Program.CreateShortcutOnDesktop () [0x00454] in : echo "zh_CN GB2312 zh_CN.GB18030 GB18030 zh_CN.GBK GBK zh_CN.UTF-8 UTF-8" >> /etc/locale.gen locale-gen # 设置语言和编码,必须设置 export LC_ALL=zh_CN.utf8 .NET(dotnet)

这里的问题我触发出来一次窗口提示,找不到怎么再次弄出来了,但总之是有线索可寻的

[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException: The type initializer for 'DevExpress.Utils.Text.FontGuard' threw an exception. ---> System.NullReferenceException: Object reference not set to an instance of an object at System.Reflection.Emit.ILGenerator.Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field) [0x0001c] in :0 at DevExpress.Utils.Text.FontGuard.EmitNativeFontAccessor () [0x00066] in :0 at DevExpress.Utils.Text.FontGuard..cctor () [0x00000] in :0 ... at (wrapper remoting-invoke-with-check) Mediinfo.WinForm.HIS.Main.DengLu..ctor() at Mediinfo.WinForm.HIS.Main.Program.FormLoginFunc (System.String[] args, System.Boolean switchSystem, System.Boolean againSystem, System.Boolean PICException) [0x00001] in

安装就很简单啦

winetricks -q dotnet40 字体问题

程序启动之后是方块乱码,字体问题有两种方式:

winetricks可以进行解决,具体可以参考winetricks fonts list 直接拷贝windows下C:/Windows/Fonts/到$WINEPREFIX/drive_c/windows/,我用的是这种比较暴力的方式 .NET4.0的bug

这里的报错是.NET4.0自身的一个错误,需要安装kb2468871补丁

System.TypeInitializationException: The type initializer for 'Mediinfo.ServiceProxy.Core.TokenLocator' threw an exception. ---> System.IO.FileLoadException: Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047) at Autofac.Builder.RegistrationData..ctor(Service defaultService) at Autofac.Builder.RegistrationBuilder`3..ctor(Service defaultService, TActivatorData activatorData, TRegistrationStyle style) at Autofac.Builder.RegistrationBuilder.ForType(Type implementationType) at Autofac.RegistrationExtensions.RegisterType(ContainerBuilder builder, Type implementationType) at Mediinfo.ServiceProxy.Core.TokenLocator..ctor() in C:\images\workspace\git4-pipeline-halo-jcjg\04.ServiceProxy\Mediinfo.ServiceProxy.Core\TokenLocator.cs:line 64 at Mediinfo.ServiceProxy.Core.TokenLocator..cctor() in C:\images\workspace\git4-pipeline-halo-jcjg\04.ServiceProxy\Mediinfo.ServiceProxy.Core\TokenLocator.cs:line 23 --- End of inner exception stack trace --- at Mediinfo.ServiceProxy.Core.TokenLocator.get_Instance() at Mediinfo.ServiceProxy.Core.ServiceClient.Invoke[T](String controller, String method, ServiceParm[] parms) in C:\images\workspace\git4-pipeline-halo-jcjg\04.ServiceProxy\Mediinfo.ServiceProxy.Core\ServiceClient.cs:line 320

很简单

winetricks -q dotnet40_kb2468871 wine自身的问题

运行后的程序有个问题,画面会进入一个卡死的状态,但实际程序是正常运行的(通过任务切换界面的任务缩略图),此时是能够进行点击交互的。

这个问题是wine的窗口管理问题导致的,可以通过开启虚拟桌面来避开,一般有两种方法:

winecfg界面在显示tab中开启虚拟桌面 wine explorer /desktop=name,1800x900 xxxx.exe命令的方法 该程序的总结 echo "zh_CN GB2312 zh_CN.GB18030 GB18030 zh_CN.GBK GBK zh_CN.UTF-8 UTF-8" >> /etc/locale.gen locale-gen export LC_ALL=zh_CN.utf8 export WINEPREFIX=/root/.wine32 export WINEARCH=win32 export WINEDEBUG=fixme-all winecfg -v win10 winetricks -q dotnet40 dotnet40_kb2468871 winetricks -q wsh57 export WINEDLLOVERRIDES="wshom.ocx=n;" regsvr32 $WINEPREFIX/drive_c/windows/system32/wshom.ocx export WINEESYNC=1 export WINE_EXPLORER_FULLSCREEN=1 # export LIBGL_ALWAYS_SOFTWARE=1 export LIBGL_ALWAYS_INDIRECT=1 cd ~/HALo cp -r Fonts $WINEPREFIX/drive_c/windows/ # LC_ALL=zh_CN.GBK wine Mediinfo.WinForm.HIS.Starter.exe # winecfg # set virtual desktop wine explorer /desktop=name,1800x900 Mediinfo.WinForm.HIS.Update.exe

Dockerfile

FROM scottyhardy/docker-wine RUN echo "zh_CN GB2312\n\ zh_CN.GB18030 GB18030\n\ zh_CN.GBK GBK\n\ zh_CN.UTF-8 UTF-8" >> /etc/locale.gen && \ locale-gen ENV LC_ALL=zh_CN.utf8 \ WINEPREFIX=/home/wineuser/.wine32 \ WINEARCH=win32 \ WINEDEBUG=fixme-all \ WINEDLLOVERRIDES="wshom.ocx=n;" \ WINE_EXPLORER_FULLSCREEN=1 \ WINEESYNC=1 \ LIBGL_ALWAYS_INDIRECT=1 # WINEESYNC=1 \ COPY HALo/Fonts/* $WINEPREFIX/drive_c/windows/Fonts/ RUN winecfg -v win10 && \ winetricks -q dotnet40 dotnet40_kb2468871 wsh57 && \ regsvr32 $WINEPREFIX/drive_c/windows/system32/wshom.ocx ENTRYPOINT ["wine","explorer","/desktop=HALo,1800x900","/home/wineuser/HALo/Mediinfo.WinForm.HIS.Update.exe"] #CMD ["wine","explorer", "/desktop=name,1800x900", "/root/HALo/Mediinfo.WinForm.HIS.Update.exe"]

之后当成命令运行即可

docker run --rm \ --env="DISPLAY" \ --volume="${XAUTHORITY:-${HOME}/.Xauthority}:/root/.Xauthority:ro" \ --volume="/tmp/.X11-unix:/tmp/.X11-unix:ro" \ --volume="/media/minecraft/Data/software/HALo:/home/wineuser/HALo" \ --ipc=host \ halo


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有