当前位置:首页> 正文

关于安装:如何从Inno Setup脚本调用.NET DLL?

关于安装:如何从Inno Setup脚本调用.NET DLL?

How can I call a .NET DLL from an Inno Setup script?

我想从Inno Setup脚本从.NET DLL(以C#编码)调用函数。

我有:

  • 在项目属性中标记了"注册COM互操作"选项,
  • 更改了AssemblyInfo.cs文件中的ComVisible设置,
  • 将这些行添加到ISS脚本中:
  • [Files]

    Source: c:\\temp\\1\\MyDLL.dll; Flags: dontcopy

    [Code]

    function MyFunction(): string;

    external 'MyFunction@files:MyDLL.dll stdcall setuponly';

    但我仍然收到以下错误:

    Runtime Error (at -1:0):

    Cannot Import dll:C:\\DOCUME~1\\foo\\LOCALS~1\\Temp\\is-LRL3E.tmp\\MyDLL.dll.

    我究竟做错了什么?


    Insta esta manera(尝试这种方式):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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;

    苏尔特(祝你好运)


    糟糕,我读过Pascal已经太久了!因此,如果您需要获取价值,那么有两种可能性:

  • 绝对支持使用C / C ++编写功能并导出功能。
  • 使用托管C ++ dll填充到您的.NET dll,并将调用公开为C接口点(这应该起作用,但是会变得凌乱)
  • 使用.exe将代码结果存储在.INI文件或注册表或临时文件中,并在设置代码部分中读取结果(现在已经很讨厌了)
  • 当我上次使用InnoSetup时,它不直接支持您的方案(从安装程序中调用.NET代码)。


    我阅读了一些有关它的内容-现在,我可以看到导入C样式函数和创建OLE对象之间的区别。

    这样的事情对我有用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [Code]
    procedure MyFunction();
    var
      oleObject: Variant;
    begin
      oleObject := CreateOleObject('MyDLL.MyDLL');

      MsgBox(oleObject.MyFunction, mbInformation, mb_Ok);
    end;

    但是它需要注册DLL文件。

    我想我将不得不创建一个命令行应用程序来从DLL调用函数。


    使用"非托管导出"库以一种可以在Inno Setup中调用的方式从C#程序集导出函数。

    • 在C#类库中实现静态方法
    • 将非托管导出NuGet程序包添加到您的项目
    • 将项目的平台目标设置为x86
    • DllExport属性添加到您的方法
    • 如果需要,请定义函数参数的封送处理(尤其是必须定义字符串参数的封送处理)。
    • 建立
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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方面:

    1
    2
    3
    4
    5
    6
    [Files]
    Source:"MyNetDll.dll"; Flags: dontcopy

    [Code]
    function RegexMatch(Pattern: string; Input: string): Boolean;
        external 'RegexMatch@files:MyNetDll.dll stdcall';

    现在,您可以使用如下功能:

    1
    2
    3
    4
    5
    6
    7
    8
    if RegexMatch('[0-9]+', '123456789') then
    begin
      Log('Matched');
    end
      else
    begin
      Log('Not matched');
    end;

    也可以看看:

    • 从C#DLL中使用非托管导出返回字符串到Inno Setup脚本
    • Inno Setup-具有依赖项的外部.NET DLL

    您正在尝试从.NET dll导入C样式的函数-这实际上与COM互操作无关。 COM interop允许您将.NET对象激活为COM对象,而不会将它们公开为C / C ++导出的函数/类型。

    如果您的函数不需要返回任何数据,为什么不制作一个简单的.exe来调用您的函数并仅在设置中运行它呢?

    另外:请参阅innosetup支持新闻组,在这里您可以获得更好的支持。


    尝试使用delayload,它用于运行时可能不存在的dll。这样就解决了问题。

    例如:

    1
    2
    3
    4
    5
    6
    [Files]
    Source: odbccp32.dll; Flags: dontcopy

    [Code]
    procedure SQLConfigDataSource(hwndParent: Integer; Frequest: Integer; LpszDriver: String; lpszAttributes: String);
    external 'SQLConfigDataSource@files:odbccp32.dll stdcall delayload';

    可以通过将任何.NET dll公开为COM对象来最好地从任何其他编程语言中调用它。请看以下示例:http://support.microsoft.com/kb/828736。这显示了如何从"非托管C ++"调用" .NET dll"。您可以用任何其他可用作COM客户端的编程语言替换"未管理的C ++"。


    用于检测dotnet框架和旧版本的Innosetup脚本可能有用。


    展开全文阅读

    相关内容