我一直为此绞尽脑汁。
我想在 Ubuntu 20.04 上的 wine 下将可执行文件添加到 PATH。尝试从 dockerfile 进行配置,但遇到了一个奇怪的问题。具体来说,我试图在 wine 下安装 python,以便您可以调用wine python
。我选择尝试使用嵌入式 python 并通过get_pip.py
(此处未显示)手动安装 pip。
在 Dockerfile 中,我有:
FROM ubuntu:20.04
RUN useradd --no-log-init -r --uid 1003 -G dialout -g 100 -s /bin/bash jenkins
# PULL /wine/winecfg from private server pre-configured
RUN dpkg --add-architecture i386 \
&& apt get update
&& apt get install -y \
libc6:i386 \
&& apt get install -y \
wine=5.0-3
RUN mkdir -p /wine/winecfg && chown -R jenkins:users /wine
# Add Embedded Python
ARG Python_Embedded_Archive=python-3.9.7-embed-win32.zip
RUN apt-get install -y unzip
COPY ${Python_Embedded_Archive} /temp/${Python_Embedded_Archive}
RUN unzip /temp/${Python_Embedded_Archive} -d /wine/python
RUN chmod +x /wine/python/python.exe
RUN chown jenkins:users /wine/python
# Switch to jenkins, which owns wine
USER jenkins:true
# Add Embedded Python to PATH in wine
COPY add_to_wine_path.sh /wine
RUN bash /wine/add_to_wine_path.sh /wine/python \
&& wine python --version
RUN wine python --version
注意:这不是完整的 dockerfile,只是相关部分
/wine/cfg 文件夹是
和add_to_wine_path.sh
:
path_to_add=$1
echo "Adding '$path_to_add' to Wine's PATH variable"
# Get clean the current path values (generally empty, but script could be called a second time)
existing_path=$(wine reg QUERY 'HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -v PATH | grep -Po '(?<=\^%).*(?=\^%)')
# If the existing path value is empty
if [ -z $existing_path" ]
then
# Set the default path values (Windows paths)
existing_path="C:\windows\system32;C:\windows"
fi
wine reg add 'HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -v PATH /t REG_EXPAND_SZ /d ^%\;&path_to_add\;$existing_path^% /f
实际情况:
当我构建 docker 镜像时,第一次调用wine python --version
成功,表明 PATH 已更新。好极了!
但是,当第二次wine python --version
在不同的块中运行时RUN
,它失败了。
在我看来,这似乎需要强制为 wine 中的所有用户更新注册表,实际上是重新启动。
因此我尝试了wineboot
各种不同的选择但仍然没有帮助。
有谁知道 Windows 注册表或 Wine 专家知道这里发生了什么吗?
答案1
我也一直在尝试在 Docker 中保留 wine 注册表更改,并且通过实验发现,在我的环境中,~/.wine/user.reg
调用后需要 1 到 2 秒的时间才能修改注册表文件 () wine reg add
。
有一个相关查询这里希望有一种方法可以同步将注册表刷新到磁盘;否则最简单的方法可能是循环直到文件被修改。
这是我在某种情况下的操作方法(此注册表更改启用了“显示点文件”选项):
RUN before=$(stat -c '%Y' /home/xclient/.wine/user.reg) \
&& wine reg add 'HKEY_CURRENT_USER\Software\Wine' /v ShowDotFiles /d Y \
&& while [ $(stat -c '%Y' /home/xclient/.wine/user.reg) = $before ]; do sleep 1; done
这是大概安全,因为它是对默认注册表的一次更改(不是很大:显然只有 16KB),但在更复杂的情况下,各种各样的事情都可能出错:
- 如果您对注册表进行了多次修改,它们可能不会同时刷新到磁盘,因此查看文件修改日期是不够的
- 当文件仍在写入磁盘时,可能会退出循环,因此最终会得到损坏的注册表文件