Domanda

Voglio chiamare una funzione da una DLL .NET (codificata in C#) da uno script Inno Setup.

Io ho:

  1. ha segnato il Registrati per l'interoperabilità COM opzione nelle proprietà del progetto,
  2. cambiato il ComVisibile impostazione nel AssemblyInfo.cs file,
  3. ho aggiunto queste righe allo script della ISS:

[File]

Fonte:c: emp\1\MyDLL.dll;Bandiere:non copiare

[Codice]

funzione La MiaFunzione():corda;

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

ma ricevo ancora il seguente errore:

Errore di runtime (a -1:0):

Impossibile importare dll:C:\DOCUME~1\foo\LOCALS~1 emp\is-LRL3E.tmp\MyDLL.dll.

Che cosa sto facendo di sbagliato?

È stato utile?

Soluzione

Oops, colpa mia, è da troppo tempo che non leggo Pascal!Quindi, se hai bisogno di ottenere il valore, ci sono un paio di possibilità:

  1. Scrivi la funzionalità in C/C++ ed esporta la funzione, che è sicuramente supportata.
  2. Utilizzare una dll C++ gestita per eseguire lo shim sulla dll .NET ed esporre la chiamata come punto di interfaccia C (dovrebbe funzionare, ma sta diventando complicato)
  3. Utilizza un file .exe per memorizzare il risultato del tuo codice in un file .INI o nel registro o in un file temporaneo e leggi il risultato nella sezione del codice di installazione (questo ora è propriamente sgradevole)

L'ultima volta che ho lavorato con InnoSetup non supportava direttamente il tuo scenario (chiamando il codice .NET dal setup).

Altri suggerimenti

Intenta de esta manera (Prova in questo modo):

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 (buona fortuna)

Ho letto qualcosa in più a riguardo: ora posso vedere la differenza tra l'importazione di una funzione in stile C e la creazione di un oggetto OLE.

Qualcosa del genere funzionerebbe per me:

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

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

ma richiede la registrazione del file DLL.

Immagino che dovrò creare un'applicazione da riga di comando per chiamare le funzioni dalla DLL.

Stai tentando di importare una funzione in stile C dalla tua dll .NET: questo non ha nulla a che fare con l'interoperabilità COM.L'interoperabilità COM consente di attivare gli oggetti .NET come oggetti COM, non li espone come funzioni/tipi esportati C/C++.

Se la tua funzione non ha bisogno di restituire alcun dato, perché non creare un semplice file .exe che chiami la tua funzione ed eseguirlo semplicemente dalla tua configurazione?

Anche:Vedi il Newsgroup di supporto di innosetup dove potresti ottenere un supporto migliore.

Usa il Libreria delle esportazioni non gestite per esportare una funzione da un assembly C#, in modo che possa essere chiamata in Inno Setup.

  • Implementare un metodo statico nella libreria di classi C#
  • Aggiungi il Esportazioni non gestite Pacchetto NuGet al progetto
  • Impostato Obiettivo della piattaforma del tuo progetto a x86
  • Aggiungi il DllExport attribuire al tuo metodo
  • Se necessario, definire un marshalling per gli argomenti della funzione (in particolare deve essere definito il marshalling degli argomenti stringa).
  • Costruire
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;
        }
    }
}

Sul lato Inno Setup:

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

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

E ora puoi usare la tua funzione in questo modo:

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

Guarda anche:

Una DLL .NET può essere richiamata al meglio da qualsiasi altro linguaggio di programmazione esponendola come oggetto COM.Dai un'occhiata a questo esempio: http://support.microsoft.com/kb/828736.Questo mostra come chiamare una ".NET dll" da "C++ non gestito".È possibile sostituire il "C++ non gestito" con qualsiasi altro linguaggio di programmazione, che può essere utilizzato come client COM.

Prova a utilizzare delayload, viene utilizzato per una DLL che potrebbe non esistere in fase di esecuzione.Questo risolve il problema.

Per esempio:

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

[Code]
procedure SQLConfigDataSource(hwndParent: Integer; Frequest: Integer; LpszDriver: String; lpszAttributes: String);
external 'SQLConfigDataSource@files:odbccp32.dll stdcall delayload';
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top