2008-09-05 13 views
9

Quiero llamar a una función desde una DLL .NET (codificada en C#) desde una secuencia de comandos Inno Setup.¿Cómo puedo llamar a una DLL .NET desde una secuencia de comandos Inno Setup?

tengo:

  1. marcó el Registro de interoperabilidad COM opción en las propiedades del proyecto,
  2. cambia el ajuste ComVisible en los AssemblyInfo.cs archivo,
  3. añadió estas líneas a la secuencia de comandos de ISS:

[Files]

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

[Code]

function MyFunction(): string;

external '[email protected]:MyDLL.dll stdcall setuponly';

pero todavía me sale el siguiente error:

Runtime Error (at -1:0):

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

¿Qué estoy haciendo mal?

Respuesta

4

¡Uy, mi mal, ha pasado demasiado tiempo desde que leí Pascal! Entonces, si necesita obtener el valor, entonces hay un par de posibilidades:

  1. Escriba la funcionalidad en C/C++ y exporte la función, eso es definitivamente compatible.
  2. Use un dll administrado de C++ 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. Use un .exe para almacenar el resultado de su código un archivo .INI o el registro o en un archivo temporal y leer el resultado en la sección del código de configuración (esto ahora es desagradable)

La última vez que trabajé con InnoSetup no admitía su escenario directamente (llamando Código .NET desde la configuración).

+0

También puede utilizar el [ 'exports' no administrado] (https://sites.google.com/site/robertgiesecke/Home/uploads/ Unmanagedexports) paquete. Un ejemplo, p. en ['this post'] (http://stackoverflow.com/q/20776847/960757). – TLama

2

Está tratando de importar una función de estilo C desde .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 en C/C++.

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

También: Vea el innosetup support newsgroups donde puede obtener un mejor soporte.

2

Leí un poco más al respecto - ahora puedo ver la diferencia entre la importación de una función de estilo C y la creación de 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.

+0

Solo por curiosidad, ¿esto funcionó? Ser capaz de llamar a .Net Dll desde Innoset sería una bendición ... –

+0

Sí, algo así funciona, pero no utilicé este método en mi instalador porque requería registrar el archivo DLL. –

0

A .NET dll se puede llamar mejor desde cualquier otro lenguaje de programación exponiéndolo como un objeto COM. Eche un vistazo a este ejemplo: http://support.microsoft.com/kb/828736. Esto muestra cómo llamar a un "DLL dll" desde "C++ no administrado".Puede reemplazar el "C++ sin control" por cualquier otro lenguaje de programación, que pueda usarse como un cliente COM.

5

Intenta of this Manera (Trate 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)

+0

Enfoque interesante Miguel. ¿Esto funciona? Intenté que funcionara algo parecido, pero no estoy seguro de haberlo configurado correctamente. ¿Puedes publicar el código de muestra que llamaría a esta rutina? Creo que estoy muy cerca de hacerlo funcionar. – Streamline

+0

Esto funcionó, gracias. –

+0

No puede usar 'RegisterServer' en .NET DLL. –

0

Trate de usar delayload, se utiliza para un archivo 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 '[email protected]:odbccp32.dll stdcall delayload'; 
2

Usa el Unmanaged Exports library a exportar una función de un conjunto C#, de una manera que puede ser llamada en la disposición de Inno.

  • implementar un método estático en la biblioteca de clase C#
  • Añadir el paquete NuGet Unmanaged Exports a su proyecto
  • Establecer Destino de la plataforma de su proyecto a x 86
  • Add the DllExport attribute to your method
  • Si es necesario, definir un cálculo de referencias para los argumentos de la función (en particular, se debe definir el cálculo de los argumentos de las cadenas).
  • 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 Inno lado de configuración:

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

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

Y ahora usted puede utilizar su función como esta:

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

Ver también:

Cuestiones relacionadas