安装程序:将其安装为第 3 方软件后,无法直接在路径环境变量中找到 python
Installer: Cannot find python in path environment variable directly after installing it as 3rd party software
对于我的软件(仅限 Windows),我使用 NSIS 创建了一个安装程序。为了让软件正常工作,我将 python(版本 3.6.5)作为第三方软件(.exe 文件)提供。此外,我需要进行 pip 升级并安装一些模块(例如 NumPy)。
我的NSIS安装程序方法如下:
运行 可执行文件 python 安装程序 :在我的安装程序中,提醒用户将 python 添加到环境中%path% 变量。提取所有文件后,执行 python 的第 3 方安装程序。 Python 已安装并添加到 %path%。
运行 小型 C++ 脚本 (PythonSetup.exe
):(除其他事项外)脚本与 python 目录使用来自 Windows.h
的 GetEnvironmentVariable
。如果 python 在路径中,那么它会执行一些命令,例如
python -m pip install --upgrade pip
python -m pip install numpy
否则它只会打印“python not found”和整个路径环境变量。
在 NSIS 中,它是这样实现的(简化):
SetOutPath "$INSTDIR\python"
File "D:\python\python-3.6.5.exe"
ExecWait '"$INSTDIR\python\python-3.6.5.exe" InstallAllUsers=1 PrependPath=1'
Sleep 500
File "D:\python\PythonSetup.exe"
ExecWait '"$INSTDIR\python\PythonSetup.exe" $INSTDIR'
Sleep 500
SetOutPath "$INSTDIR"
Delete "$INSTDIR\python\python-3.6.5.exe"
Delete "$INSTDIR\python\PythonSetup.exe"
RmDir "$INSTDIR\python"
我的问题是:
PythonSetup.exe
在 %path% 变量中找不到 python 目录。打印我使用GetEnvironmentVariable
从Windows.h
得到的路径,可以看到它得到的路径确实不包含python目录
- 强制执行上面提到的命令我得到错误:
'python.exe' is not recognized as an internal or external command, operable program or batch file.
- 然而检查 Windows
System Properties > Advanced > Environment Variables
中的 %path% 变量显示 python 目录确实已添加到路径变量中。我在 PyhtonSetup.exe
的运行时检查了这个,即在 NSIS 行 ExecWait '"$INSTDIR\python\PythonSetup.exe" $INSTDIR'
. 期间
- NSIS 安装程序完成后立即执行
PythonSetup.exe
就可以了。
我试过了
- 更长
Sleep
- 其他 python 架构(32 位与 64 位)
- 手动查找 python 目录并以这种方式调用
python.exe
,例如
C:\Program Files\python36-32\python.exe -m pip install numpy
有谁知道在PythonSetup.exe
中GetEnvironmentVariable
返回的路径中找不到python目录的原因同时它可以在系统属性中看到?
我觉得我可能遗漏了一些明显的东西......
当用户登录时 Windows 从注册表的用户和机器部分读取环境变量,并使用这些合并的变量启动初始进程。创建新进程时,它会继承其父进程的环境(除非您在启动进程时指定新的自定义环境)。
应用程序应该在更改环境时广播 WM_SETTINGCHANGE 消息,但实际上 Explorer 是唯一侦听此消息并动态更新其环境的应用程序。一个主要原因是 Explorer 使用未记录的函数来执行此更新,并且其他应用程序实现相同的功能是一个主要的痛苦。
对于使用自定义变量的应用程序,很容易在安装程序中设置此值,以便由它启动的子进程继承:
System::Call 'KERNEL32::SetEnvironmentVariable(t "MYAPP_DIR", t "$InstDir")'
由于各种原因,以相同的方式更新 %PATH% 很棘手:
- NSIS 有字符串长度限制,长的 %PATH% 可能不适合。
- %PATH% 是 HKCU 和 HKLM 值的组合,需要一些字符串操作才能正确连接它们。
我在安装程序中更新 %PATH% 的唯一建议是使用 EnVar plug-in:
EnVar::Update "" "PATH"
Pop [=11=] ; "0" on success
对于我的软件(仅限 Windows),我使用 NSIS 创建了一个安装程序。为了让软件正常工作,我将 python(版本 3.6.5)作为第三方软件(.exe 文件)提供。此外,我需要进行 pip 升级并安装一些模块(例如 NumPy)。
我的NSIS安装程序方法如下:
运行 可执行文件 python 安装程序 :在我的安装程序中,提醒用户将 python 添加到环境中%path% 变量。提取所有文件后,执行 python 的第 3 方安装程序。 Python 已安装并添加到 %path%。
运行 小型 C++ 脚本 (
PythonSetup.exe
):(除其他事项外)脚本与 python 目录使用来自Windows.h
的GetEnvironmentVariable
。如果 python 在路径中,那么它会执行一些命令,例如
python -m pip install --upgrade pip
python -m pip install numpy
否则它只会打印“python not found”和整个路径环境变量。
在 NSIS 中,它是这样实现的(简化):
SetOutPath "$INSTDIR\python"
File "D:\python\python-3.6.5.exe"
ExecWait '"$INSTDIR\python\python-3.6.5.exe" InstallAllUsers=1 PrependPath=1'
Sleep 500
File "D:\python\PythonSetup.exe"
ExecWait '"$INSTDIR\python\PythonSetup.exe" $INSTDIR'
Sleep 500
SetOutPath "$INSTDIR"
Delete "$INSTDIR\python\python-3.6.5.exe"
Delete "$INSTDIR\python\PythonSetup.exe"
RmDir "$INSTDIR\python"
我的问题是:
PythonSetup.exe
在 %path% 变量中找不到 python 目录。打印我使用GetEnvironmentVariable
从Windows.h
得到的路径,可以看到它得到的路径确实不包含python目录- 强制执行上面提到的命令我得到错误:
'python.exe' is not recognized as an internal or external command, operable program or batch file.
- 然而检查 Windows
System Properties > Advanced > Environment Variables
中的 %path% 变量显示 python 目录确实已添加到路径变量中。我在PyhtonSetup.exe
的运行时检查了这个,即在 NSIS 行ExecWait '"$INSTDIR\python\PythonSetup.exe" $INSTDIR'
. 期间
- NSIS 安装程序完成后立即执行
PythonSetup.exe
就可以了。
我试过了
- 更长
Sleep
- 其他 python 架构(32 位与 64 位)
- 手动查找 python 目录并以这种方式调用
python.exe
,例如
C:\Program Files\python36-32\python.exe -m pip install numpy
有谁知道在PythonSetup.exe
中GetEnvironmentVariable
返回的路径中找不到python目录的原因同时它可以在系统属性中看到?
我觉得我可能遗漏了一些明显的东西......
当用户登录时 Windows 从注册表的用户和机器部分读取环境变量,并使用这些合并的变量启动初始进程。创建新进程时,它会继承其父进程的环境(除非您在启动进程时指定新的自定义环境)。
应用程序应该在更改环境时广播 WM_SETTINGCHANGE 消息,但实际上 Explorer 是唯一侦听此消息并动态更新其环境的应用程序。一个主要原因是 Explorer 使用未记录的函数来执行此更新,并且其他应用程序实现相同的功能是一个主要的痛苦。
对于使用自定义变量的应用程序,很容易在安装程序中设置此值,以便由它启动的子进程继承:
System::Call 'KERNEL32::SetEnvironmentVariable(t "MYAPP_DIR", t "$InstDir")'
由于各种原因,以相同的方式更新 %PATH% 很棘手:
- NSIS 有字符串长度限制,长的 %PATH% 可能不适合。
- %PATH% 是 HKCU 和 HKLM 值的组合,需要一些字符串操作才能正确连接它们。
我在安装程序中更新 %PATH% 的唯一建议是使用 EnVar plug-in:
EnVar::Update "" "PATH"
Pop [=11=] ; "0" on success