Pregunta

Quiero llamar a una función desde una DLL .NET (codificada en C#) desde un script de Inno Setup.

Tengo:

  1. marcó el Regístrese para la interoperabilidad COM opción en las propiedades del proyecto,
  2. cambiado el ComVisible ajuste en el AsambleaInfo.cs archivo,
  3. Agregué estas líneas al script de la ISS:

[Archivos]

Fuente:c: emp\1\MiDLL.dll;Banderas:no copiar

[Código]

función MiFunción():cadena;

externo 'MiFunción@archivos:MyDLL.dll stdcall setuponly';

pero sigo recibiendo el siguiente error:

Error de tiempo de ejecución (a -1:0):

No se puede importar dll:C:\DOCUME~1\foo\LOCALS~1 emp\is-LRL3E.tmp\MyDLL.dll.

¿Qué estoy haciendo mal?

¿Fue útil?

Solución

Vaya, qué pena, ¡ha pasado demasiado tiempo desde que leí a Pascal!Entonces, si necesita obtener el valor, existen un par de posibilidades:

  1. Escriba la funcionalidad en C/C++ y exporte la función, eso definitivamente es compatible.
  2. Utilice una DLL de C++ administrada para ajustar su DLL de .NET y exponer la llamada como un punto de interfaz C (esto debería funcionar, pero se está volviendo complicado)
  3. Utilice un .exe para almacenar el resultado de su código en un archivo .INI o el registro o en un archivo temporal y lea el resultado en la sección del código de configuración (esto ahora es realmente desagradable)

La última vez que trabajé con InnoSetup, no era compatible con su escenario directamente (llamando al código .NET desde la configuración).

Otros consejos

Intenta de esta manera (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;

Suerte (buena suerte)

Leí un poco más sobre esto; ahora puedo ver la diferencia entre importar una función de estilo C y crear un objeto OLE.

Algo como esto funcionaría para mí:

[Code]
procedure MyFunction();
var
  oleObject: Variant;
begin
  oleObject := CreateOleObject('MyDLL.MyDLL');

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

pero requiere registrar el archivo DLL.

Supongo que tendré que crear una aplicación de línea de comandos para llamar a las funciones desde la DLL.

Está intentando importar una función de estilo C desde su .NET dll; esto realmente no tiene nada que ver con la interoperabilidad COM.La interoperabilidad COM le permite activar sus objetos .NET como objetos COM, no los expone como funciones/tipos exportados a C/C++.

Si su función no necesita devolver ningún dato, ¿por qué no crear un .exe simple que llame a su función y simplemente ejecutarlo desde su configuración?

También:Ver el grupos de noticias de soporte innosetup donde podría obtener un mejor soporte.

Utilizar el Biblioteca de exportaciones no administradas para exportar una función desde un ensamblado de C#, de manera que se pueda llamar en Inno Setup.

  • Implementar un método estático en la biblioteca de clases C#
  • Añade el Exportaciones no administradas Paquete NuGet para su proyecto
  • Colocar Objetivo de plataforma de tu proyecto para x86
  • Añade el DllExport atribuye a tu método
  • Si es necesario, defina una clasificación para los argumentos de la función (en particular, se debe definir la clasificación de los argumentos de cadena).
  • Construir
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;
        }
    }
}

En el lado de Inno Configuración:

[Files]
Source: "MyNetDll.dll"; Flags: dontcopy

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

Y ahora puedes usar tu función así:

if RegexMatch('[0-9]+', '123456789') then
begin
  Log('Matched');
end
  else
begin
  Log('Not matched');
end;

Ver también:

La mejor manera de llamar a una DLL .NET desde cualquier otro lenguaje de programación es exponiéndola como un objeto COM.Echale un vistazo a éste ejemplo: http://support.microsoft.com/kb/828736.Esto muestra cómo llamar a una "dll .NET" desde "C++ no administrado".Puede reemplazar el "C++ no administrado" por cualquier otro lenguaje de programación que pueda usarse como cliente COM.

Intente usar delayload, se usa para una DLL que puede no existir en tiempo de ejecución.Esto resuelve el problema.

Por ejemplo:

[Files]
Source: odbccp32.dll; Flags: dontcopy

[Code]
procedure SQLConfigDataSource(hwndParent: Integer; Frequest: Integer; LpszDriver: String; lpszAttributes: String);
external 'SQLConfigDataSource@files:odbccp32.dll stdcall delayload';
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top