将 DLL 导入 Inno Setup 时出现问题

发布于 2024-09-15 19:31:14 字数 781 浏览 7 评论 0原文

我正在 Inno Setup 安装脚本中导入 C++ DLL。 DLL代码如下:

void __stdcall SetFbParam(
        char *dbFileName,char *dbTableName,char *dbParamName,char *dbParamValue) {
    // of no use here and doesn't change anything
}

在Inno Setup中,我使用导入它

procedure FBset(dbFileName,dbTableName,dbParamName,dbParamValue: String;);
    external 'SetFbParam@files:MyDll.dll stdcall setuponly';

但是,在启动安装程序期间我总是收到运行时错误,说它无法导入我的dll。我尝试了各种调用约定,但总是失败。 如果它很重要的话,我正在运行带有 UAC 的 Win7 x64(安装程序请求权限提升,然后崩溃)。

确切的消息是:

错误
运行时错误(-1:0):
无法导入
dll:C:\Users\Nevod\AppData\Local\Temp\is-6LOEC.tmp\MyDll.dll

dll 就在那里。

谢谢!

I am importing an C++ DLL in an Inno Setup install script. The DLL code is as follows:

void __stdcall SetFbParam(
        char *dbFileName,char *dbTableName,char *dbParamName,char *dbParamValue) {
    // of no use here and doesn't change anything
}

In the Inno Setup, I import it using

procedure FBset(dbFileName,dbTableName,dbParamName,dbParamValue: String;);
    external 'SetFbParam@files:MyDll.dll stdcall setuponly';

However, I always get a runtime error during launch of the installer, saying that it cannot import my dll. I tried it with various calling conventions, but it always fails.
If it's of any importance, I'm running Win7 x64 with UAC on (the installer requests rights elevation and crashes after that).

The exact message is:

Error
Runtime error (at -1:0):
Cannot import
dll:C:\Users\Nevod\AppData\Local\Temp\is-6LOEC.tmp\MyDll.dll

The dll is there.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

木有鱼丸 2024-09-22 19:31:14

MyDll.dll 是 32 位吗?

MyDll.dll 是否依赖于同一目录中的任何其他 DLL?如果是这样,您需要在 MyDll.dll 之后列出这些 DLL 的名称,以确保它们在MyDll.dll之前提取已加载,您可能还需要 loadwithalteredsearchpath 选项。 帮助中的示例:

procedure ADllFunc(hWnd: Integer; lpText, lpCaption: String; uType: Cardinal);
// A.dll depends on B.dll
external 'ADllFunc@files:A.dll,B.dll stdcall loadwithalteredsearchpath';

Is MyDll.dll 32-bit?

Does MyDll.dll depend on any other DLLs in the same directory? If so, you need to list the name(s) of those DLLs after MyDll.dll to ensure that they are extracted before MyDll.dll is loaded, and you likely need the loadwithalteredsearchpath option as well. Example from the help:

procedure ADllFunc(hWnd: Integer; lpText, lpCaption: String; uType: Cardinal);
// A.dll depends on B.dll
external 'ADllFunc@files:A.dll,B.dll stdcall loadwithalteredsearchpath';
以酷 2024-09-22 19:31:14

(我知道它很旧,但也许其他一些也碰到了这个)

最有可能的是该函数的名称在 C++ DLL 中被破坏了。我也遇到了同样的问题,重新编译dll就解决了。简而言之:

如果您从 C++ 导出类似的内容:

void __stdcall foo() 

您将得到一个名为 (Visual Studio) 的函数:

?foo@@YGXXZ

为了防止名称修改,您应该使用 extern "C" 指令。示例(Visual Studio)

extern "C" __declspec( dllexport ) void __stdcall foo()

但是我发现 Visual Studio 将继续损坏,并且您会得到类似以下内容:

_foo@0

我能够获得干净名称的唯一方法解释如下:
C++ DLL 导出:装饰/损坏的名称

罪魁祸首确实是 __stdcall。如果您从声明中删除它:

extern "C" __declspec( dllexport ) void foo()

您将再次获得干净的导出,即使没有 DEF 文件。 IMO 这应该足够好了,因为上面的代码声明了一个“C”导出函数,并且 C 的默认调用约定是 stdcall。然而,我没有时间和配置来验证这一点,因为添加 DEF 文件比导航 asm 代码和检查堆栈指针要容易得多:)

(I know it is old but maybe some other hits this one too)

Most probably the name of the function is mangled in the C++ DLL. I had the same problem and I was able to solve it by recompiling the dll. In short:

If you export from C++ something like:

void __stdcall foo() 

you will get a function called (Visual Studio):

?foo@@YGXXZ

To prevent name mangling you should use extern "C" directive. Example (Visual Studio)

extern "C" __declspec( dllexport ) void __stdcall foo()

However I have found that Visual Studio will continue to mangle and you get something like:

_foo@0

The sole way I was able to get clean names is explained here:
C++ DLL Export: Decorated/Mangled names

And the culprit is indeed __stdcall. If you remove that from your declaration:

extern "C" __declspec( dllexport ) void foo()

you will again get a clean export, even without a DEF file. IMO this should be good enough, as the code above declares a "C" exported function and the default calling convention for C is stdcall. However I haven't had the time and disposition to validate this as adding a DEF file is way easier than navigating asm code and check stack pointers :)

∞琼窗梦回ˉ 2024-09-22 19:31:14

为了在 Inno Setup 的 [Code] 部分中使用 DLL,请确保:

  • DLL 处于 32 位模式(即使安装程序是为 64 位构建并在 64 位模式下运行)
  • 导出函数具有
    extern "C" __declspec( dllexport )
    修饰符
  • 使用 cdecl 调用约定,因为 stdcall 会破坏名称(https://learn.microsoft.com/en-us/cpp/cpp/stdcall)。当然,可以在 Inno Setup 导入语句中指定损坏的名称。但使用cdecl似乎更容易。

In order to use DLLs in Inno Setup's [Code] section please make sure:

  • DLL is in 32 bit mode (even if the installer is built for 64bit and is running in 64bit mode)
  • exported functions have
    extern "C" __declspec( dllexport )
    modifier
  • use cdecl calling convention because stdcall mangles name (https://learn.microsoft.com/en-us/cpp/cpp/stdcall). Of course it is possible to specify mangled name in Inno Setup import statement. But it seems easier to just use cdecl.
很糊涂小朋友 2024-09-22 19:31:14

正如其他答案中提到的,不要忘记嵌入 DLL 的所有依赖项。不过,如果它是您的 DLL,最好摆脱(或至少减少)依赖关系。

  • 例如,在 Visual Studio 中构建 C++ DLL 时,静态链接运行时,而不是动态链接。

    在项目属性中,转到C/C++ >代码生成>运行时库并选择多线程(不是DLL)。

  • 还有一些工具可以嵌入其他外部依赖项。

    请参阅在已编译的可执行文件中嵌入 DLL

As mentioned in other answers, do not forget to embed all dependencies of your DLL. Though if it is your DLL, better might be to get rid of (or at least reduce) the dependencies.

  • For example when building C++ DLL in Visual Studio, link the runtime statically, not dynamically.

    In project Properties, go to C/C++ > Code Generation > Runtime Library and select Multi-threaded (not DLL).

  • There are also tools that can embed other external dependencies.

    See Embedding DLLs in a compiled executable

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文