PyInstaller Kivy 应用程序找不到数据库后的 NSIS

NSIS after PyInstaller Kivy app can't find database

我成功地使用 PyInstaller 和我的 app.exe 运行 为 Windows 打包了我的 Kivy 应用程序,没有任何问题。 (.spec: )

为了便于分发,我想将我的文件打包成一个独立的 .exe。我的 .nsi 文件:

SilentInstall silent
Section
InitPluginsDir
Setoutpath KanjiOrigin
File /r "dist\KanjiOrigin\*"
ExecWait "dist\KanjiOrigin\KanjiOrigin.exe"
Setoutpath $TEMP
SectionEnd

A .exe 构建无误:http://pastebin.com/h91jzGgY

然而,当 运行ning 这个由 NSIS 制作的 .exe 时,应用程序 运行s 直到我需要连接到我位于 data\db\Kanji-story.db 的内部数据库,但找不到。 (打开.exe的时候在里面,所以数据库已经包含了)

sqlite3.OperationalError: unable to open database: data\db\Kanji-story.db

当我用 7zip 解压缩我的 .exe 并尝试从 PyInstaller 运行 KanjiOrigin.exe 时,我收到以下错误:D:\path\KanjiOrigin\KanjiOrigin.exe is not a valid Win32 application。 (不确定这是否相关)。

编辑 2

我不知道发生了什么变化,但是现在用 7zip 打开 NSIS .exe 时,提取 PyInstaller .exe 时不会再出现错误。 但是,当尝试 运行 提取的 PyInstaller .exe 时,出现以下错误:

PyInstaller Bootloader 3.x
LOADER: executable is D:\path\KanjiOrigin\KanjiOrigin.exe
LOADER: homepath is D:\path\KanjiOrigin
LOADER: _MEIPASS2 is NULL
LOADER: archivename is D:\path\KanjiOrigin\KanjiOrigin.exe
LOADER: pyi_arch_check_cookie failed
LOADER: archivename is D:\path\KanjiOrigin\KanjiOrigin.pkg
LOADER: Cannot open archive: D:\path\KanjiOrigin\KanjiOrigin.pkg
Cannot open self D:\path\KanjiOrigin\KanjiOrigin.exe or archive D:\path\KanjiOrigin\KanjiOrigin.pkg

此外,包含的数据库似乎没有损坏,因为提取后我可以使用 sqlitebrowser (http://sqlitebrowser.org/) 成功打开它。

我做错了什么?是Setoutpath $TEMP吗?

编辑:

如果我在 NSIS 创建的 .exe 之外手动包含具有相同文件夹结构 (data\db\Kanji-story.db) 的数据库,它能找到数据库吗?为什么它能找到外部数据库,但找不到 NSIS .exe 中包含的内部数据库?

看起来你只是从某个地方复制了一些代码,但没有理解它。

SilentInstall silent
Section
InitPluginsDir
SetOutPath $Pluginsdir ; This must be a full path
File myapp.exe
ExecWait '"$pluginsdir\myapp.exe"' ; This should be a full path as well.
SetOutPath $TEMP
SectionEnd

对于临时提取 .exe 然后从 %Temp% 文件夹中执行它的代码来说是典型的,但您不会在安装程序中执行此操作,只有在您创建可移植应用程序包装器时才这样做。

您代码中的另一个问题是您只使用了相对路径。来自 SetOutPath 的文档:

Must be a full pathname, usually is just $INSTDIR

至于 SetOutPath $TEMP 的作用; SetOutPath 在内部设置进程的当前目录,当应用程序处于 运行 时无法删除当前目录,因此最后将其设置为 $TEMP 只是 only 的解决方法如果您使用 SetOutPath $PluginsDir 则需要使用它,因为您希望 NSIS 能够在它退出之前删除 $PluginsDir。

如果您正在使用 NSIS 编写可移植应用程序包装器,那么您应该确保您使用的是完整路径,然后它应该可以工作。另一方面,如果你正在编写一个普通的安装程序,那么你不应该处理 $PluginsDir,你应该使用 SetOutPath $InstDir 并且 InstallDir 属性应该设置为类似于 "$ProgramFiles\MyApp