windows - 调用外部 dll 时出现 InnoSetup 错误“无法调用 proc”
问题描述
我们的 InnoSetup 使用外部 dll 来抓取并检查 xml 文件中的数据文件路径。这在大多数情况下都可以正常工作,Windows XP、7、10(32/64 位)。但对于少数用户来说,这失败了,对我来说,它在 macOS 10.15 的 Crossover 19 中失败了。所以首先我在 inno 脚本中添加了一个延迟加载,以克服“无法导入 dll”运行时错误。
但后来我得到“无法调用proc”运行时错误。InnoSetup 调试器将我指向procedure GetExultGamePaths
我们的脚本。
我们的dll中的代码:
extern "C" {
__declspec(dllexport) void __stdcall GetExultGamePaths(char *ExultDir, char *BGPath, char *SIPath, int MaxPath) {
MessageBoxDebug(nullptr, ExultDir, "ExultDir", MB_OK);
MessageBoxDebug(nullptr, BGPath, "BGPath", MB_OK);
MessageBoxDebug(nullptr, SIPath, "SIPath", MB_OK);
int p_size = strlen(ExultDir) + strlen("/exult.cfg") + MAX_STRLEN;
char *p = new char[p_size];
// Get the complete path for the config file
Path config_path(ExultDir);
config_path.AddString("exult.cfg");
config_path.GetString(p, p_size);
setup_program_paths();
const static char *si_pathdef = CFG_SI_NAME;
const static char *bg_pathdef = CFG_BG_NAME;
MessageBoxDebug(nullptr, ExultDir, p, MB_OK);
try {
// Open config file
Configuration config;
if (get_system_path("<CONFIG>") == ".")
config.read_config_file(p);
else
config.read_config_file("exult.cfg");
std::string dir;
// SI Path
config.value("config/disk/game/serpentisle/path", dir, si_pathdef);
if (dir != si_pathdef) {
Path si(ExultDir);
si.AddString(dir.c_str());
si.GetString(SIPath, MaxPath);
} else {
std::strncpy(SIPath, si_pathdef, MaxPath);
}
// BG Path
config.value("config/disk/game/blackgate/path", dir, bg_pathdef);
if (dir != bg_pathdef) {
Path bg(ExultDir);
bg.AddString(dir.c_str());
bg.GetString(BGPath, MaxPath);
} else {
std::strncpy(BGPath, bg_pathdef, MaxPath);
}
} catch (...) {
std::strncpy(BGPath, bg_pathdef, MaxPath);
std::strncpy(SIPath, si_pathdef, MaxPath);
}
delete [] p;
}
InnoSetup 脚本部分
procedure GetExultGamePaths(sExultDir, sBGPath, sSIPath: String; iMaxPath: Integer);
external 'GetExultGamePaths@files:exconfig.dll stdcall delayload';
procedure CurPageChanged(CurPageID: Integer);
var
sBGPath: String;
sSIPath: String;
begin
if CurPageID = DataDirPage.ID then begin
if bSetPaths = False then begin
setlength(sBGPath, 1024);
setlength(sSIPath, 1024);
GetExultGamePaths(ExpandConstant('{app}'), sBGPath, sSIPath, 1023 );
BGEdit.Text := sBGPath;
SIEdit.Text := sSIPath;
end;
end;
end;
这GetExultGamePaths(ExpandConstant('{app}'), sBGPath, sSIPath, 1023 );
就是产生“无法调用proc”运行时错误的原因。
我不知道为什么只有少数系统会失败。我们的 dll 和脚本的完整代码位于https://github.com/exult/exult/blob/master/win32/ dll 的代码位于 exconfig.* 中,InnoSetup 脚本位于 exult_installer.iss
解决方案
通过 Piotr 在我们的 Wine 错误报告https://bugs.winehq.org/show_bug.cgi?id=49033中的帮助,发现使用 mingw 工具“dllwrap”被破坏并添加了无效的重定位数据。
不使用 dllwrap 是解决方案,并为我的 Wine/Crossover 安装修复了它。仍在等待最后一个用户报告在实际安装 Windows 10 时遇到此问题的用户。
谢谢你的帮助
推荐阅读
- mysql - 如何使用 Qt 上的 INSERT Query 修复 synthax 错误?
- python - 熊猫滚动在窗口中获得最频繁的值
- android - 由于代码问题,android-10.0.0_r10 的 AOSP 构建失败
- flutter - Flutter / 小部件放置问题 - 文本表单出现白屏
- python - Pandas 对值进行排序并在条件下忽略 NaN 值
- stripe-payments - 如何在 Stripe webhook 中获取产品信息(退款)
- python - Trying to understand what's happening over key=lambda x: (count[x], -x)?
- wordpress - WordPress网站中的汉堡包按钮问题
- excel - Excel VBA 'dim as Variant' 不允许 'for each' 循环
- vue.js - 静态元素上的Vue转换不起作用