代码之家  ›  专栏  ›  技术社区  ›  Marek Grzenkowicz

如何从Inno安装脚本调用.NET DLL?

  •  9
  • Marek Grzenkowicz  · 技术社区  · 18 年前

    我想从一个.NET DLL(用C编码)调用一个来自Inno安装脚本的函数。

    我有:

    1. 标志着 注册COM互操作 项目属性中的选项,
    2. 改变了 可看见的 设置在 汇编语言 文件,
    3. 将这些行添加到ISS脚本:

    [文件]

    源:c:\temp\1\mydll.dll;标志:dontcopy

    [代码]

    函数myfunction():字符串;

    外部'myfunction@files:mydll.dll stdcall setuponly';

    但我仍然得到以下错误:

    运行时错误(在-1:0):

    无法导入dll:c:\docume~1\foo\locals~1\temp\is-lrl3e.tmp\mydll.dll。

    我做错什么了?

    8 回复  |  直到 9 年前
        1
  •  4
  •   Simon Steele    18 年前

    哎呀,我的错,我已经很久没读过帕斯卡了!因此,如果您需要获得价值,那么有两种可能性:

    1. 在C/C++中编写功能并导出函数,这是明确支持的。
    2. 使用一个托管C++ DLL将SIMM映射到.NET DLL,并将调用暴露为C接口点(这应该工作,但它变得混乱)。
    3. 使用.exe将代码的结果存储在.ini文件、注册表或临时文件中,并在“设置代码”部分读取结果(这现在很糟糕)

    我上次使用InnoSetup时,它不直接支持您的场景(从安装程序调用.NET代码)。

        2
  •  5
  •   Miguel Vivanco    16 年前

    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;
    

    苏尔特(祝你好运)

        3
  •  3
  •   Marek Grzenkowicz    18 年前

    我读了更多关于它的内容——现在我可以看到导入C样式函数和创建OLE对象之间的区别。

    像这样的东西对我很有用:

    [Code]
    procedure MyFunction();
    var
      oleObject: Variant;
    begin
      oleObject := CreateOleObject('MyDLL.MyDLL');
    
      MsgBox(oleObject.MyFunction, mbInformation, mb_Ok);
    end;
    

    但它需要注册dll文件。

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

        4
  •  2
  •   Simon Steele    18 年前

    您正试图从.NET DLL导入C样式的函数-这与COM互操作没有任何关系。COM互操作允许你激活你的.NET对象作为COM对象,它不会将它们暴露为C/C++导出的函数/类型。

    如果您的函数不需要返回任何数据,为什么不创建一个简单的.exe来调用您的函数并从安装程序中运行它呢?

    另外,请参见 innosetup support newsgroups 在那里你可以得到更好的支持。

        5
  •  2
  •   Martin Prikryl    9 年前

    使用 Unmanaged Exports library 从C程序集中导出一个函数,方法是在Inno设置中调用该函数。

    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设置端:

    [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;
    

    参见:

        6
  •  0
  •   Juba    17 年前

    通过将.NET dll公开为COM对象,可以从任何其他编程语言中最好地调用它。看看这个例子: http://support.microsoft.com/kb/828736 . 这显示了如何从“非托管C++”调用“.NET DLL”。您可以用任何其他编程语言来替换“unAMangeC+”,它可以用作COM客户机。

        7
  •  0
  •   Marek Grzenkowicz    14 年前

    尝试使用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';