如何从 Inno Setup 脚本调用 .NET DLL?
-
09-06-2019 - |
题
我想从 Inno Setup 脚本调用 .NET DLL(用 C# 编码)中的函数。
我有:
- 标记了 注册 COM 互操作 项目属性中的选项,
- 改变了 康可视 设置在 AssemblyInfo.cs 文件,
- 将这些行添加到 ISS 脚本中:
[文件]
来源:c: emp\1\MyDLL.dll;标志:不要复制
[代码]
函数 MyFunction():细绳;
外部 'MyFunction@files:MyDLL.dll stdcall setuponly';
但我仍然收到以下错误:
运行时错误(-1:0):
无法导入 dll:C:\DOCUME~1\foo\LOCALS~1 emp\is-LRL3E.tmp\MyDLL.dll。
我究竟做错了什么?
解决方案
哎呀,我的错,我已经太久没有读过帕斯卡了!因此,如果您需要获取该值,那么有几种可能性:
- 用 C/C++ 编写功能并导出函数,这是绝对支持的。
- 使用托管 C++ dll 填充您的 .NET dll,并将调用公开为 C 接口点(这应该可以工作,但会变得混乱)
- 使用 .exe 将代码结果存储在 .INI 文件或注册表或临时文件中,并在安装代码部分读取结果(现在这确实很糟糕)
当我上次使用 InnoSetup 时,它不直接支持您的场景(从安装程序调用 .NET 代码)。
其他提示
Intenta de esta manera(尝试这种方式):
Var
obj: Variant
va: MyVariableType;
Begin
//Starting
ExtractTemporaryFile('MyDll.dll');
RegisterServer(False, ExpandConstant('{tmp}\MyDll.dll'), False);
obj := CreateOleObject('MyDll.MyClass');
//Using
va := obj.MyFunction();
//Finishing
UnregisterServer(False, ExpandConstant('{tmp}\MyDll.dll'), False);
DeleteFile('{tmp}\MyDll.dll');
End;
苏尔特(祝你好运)
我阅读了更多相关内容 - 现在我可以看到导入 C 样式函数和创建 OLE 对象之间的区别。
像这样的东西对我有用:
[Code]
procedure MyFunction();
var
oleObject: Variant;
begin
oleObject := CreateOleObject('MyDLL.MyDLL');
MsgBox(oleObject.MyFunction, mbInformation, mb_Ok);
end;
但它需要注册DLL文件。
我想我必须创建一个命令行应用程序来调用 DLL 中的函数。
您正在尝试从 .NET dll 导入 C 样式函数 - 这实际上与 COM 互操作没有任何关系。COM 互操作允许您将 .NET 对象激活为 COM 对象,它不会将它们公开为 C/C++ 导出函数/类型。
如果您的函数不需要返回任何数据,为什么不创建一个简单的 .exe 来调用您的函数并从您的设置中运行它呢?
还:请参阅 innosetup 支持新闻组 您可能会得到更好的支持。
使用 非托管导出库 从 C# 程序集中导出函数,以便可以在 Inno Setup 中调用该函数。
- 在C#类库中实现静态方法
- 添加 不受管理的出口 NuGet 包到您的项目
- 放 平台目标 您的项目的 x86
- 添加
DllExport
归因于你的方法 - 如果需要,请为函数参数定义封送处理(特别是必须定义字符串参数的封送处理)。
- 建造
using RGiesecke.DllExport;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace MyNetDll
{
public class MyFunctions
{
[DllExport(CallingConvention = CallingConvention.StdCall)]
public static bool RegexMatch(
[MarshalAs(UnmanagedType.LPWStr)]string pattern,
[MarshalAs(UnmanagedType.LPWStr)]string input)
{
return Regex.Match(input, pattern).Success;
}
}
}
在 Inno Setup 端:
[Files]
Source: "MyNetDll.dll"; Flags: dontcopy
[Code]
function RegexMatch(Pattern: string; Input: string): Boolean;
external 'RegexMatch@files:MyNetDll.dll stdcall';
现在你可以像这样使用你的函数:
if RegexMatch('[0-9]+', '123456789') then
begin
Log('Matched');
end
else
begin
Log('Not matched');
end;
也可以看看:
通过将 .NET dll 公开为 COM 对象,可以从任何其他编程语言调用它。看一下这个例子: http://support.microsoft.com/kb/828736. 。这展示了如何从“非托管C++”调用“.NET dll”。您可以用任何其他可用作 COM 客户端的编程语言来替换“未管理的 C++”。
尝试使用delayload,它用于运行时可能不存在的dll。这样就解决了问题。
例如:
[Files]
Source: odbccp32.dll; Flags: dontcopy
[Code]
procedure SQLConfigDataSource(hwndParent: Integer; Frequest: Integer; LpszDriver: String; lpszAttributes: String);
external 'SQLConfigDataSource@files:odbccp32.dll stdcall delayload';
Innosetup脚本检测dotnet框架和旧版本 可能有一些用处。