2017-08-30 4 views
2

Ich versuche, eine benutzerdefinierte DLL in einem Inno-Setup-Skript während der Installation zu verwenden. Ich habe eine sehr einfache Funktion geschrieben, die im Grunde eine Verbindungszeichenfolge für eine MySQL-Datenbank mit dem MySQL .NET-Konnektor überprüft (es gibt keinen MySQL-Client auf dem Zielserver). Der Code dieser exportierten Funktion ist:Inno Setup - Externe .NET DLL mit Abhängigkeiten

public class DbChecker 
{ 
    [DllExport("CheckConnexion", CallingConvention.StdCall)] 
    public static int CheckConnexion([MarshalAs(UnmanagedType.LPStr)] string connexionString) 
    { 
     int success; 
     try 
     { 
      MySqlConnection connection = new MySqlConnection(connexionString); 
      connection.Open(); 
      connection.Close(); 
      success = 0; 
     } 
     catch (Exception) 
     { 
      success = 1; 
     } 
     return success; 
    } 
} 

Die Funktion importiert wird auf diese Weise in Inno Setup:

[Files] 
Source: "..\..\MyDll\bin\x86\Release\*"; Flags: dontcopy; 

und

[Code] 
function CheckConnexion(connexionString: AnsiString): Integer; 
external '[email protected]:MyDll.dll,MySql.Data.dll stdcall setuponly loadwithalteredsearchpath';` 

Das Problem ist, dass die Einrichtung eine Ausnahme wirft auf Laufzeit:

Laufzeitfehler (bei 53: 207):

Externe Ausnahme E0434352.

Ich glaube, ich habe den files Präfix verwenden, da die Funktion im NextButtonClick Ereignishandler aufgerufen wird, bevor Dateien in das {app} Verzeichnis kopiert werden.

Sowohl MyDll.dll als auch MySql.Data.dll werden zur Laufzeit korrekt in das Verzeichnis {tmp} extrahiert.

Ich versuchte sowohl mit als auch ohne das loadwithalteredsearchpath Flag mit dem gleichen Ergebnis.

Was ich fand, ist, dass dieser Fehlercode ein generischer .NET-Laufzeitfehlercode ist.

Wenn ich entfernen Sie den Teil MySql.Data mit es perfekt funktioniert gut (außer, dass es tut nichts ...)

Wie auf anderen Threads geraten Ich habe versucht, den Fehler in meiner .NET-Code anmelden EventLog mit und UnhandledException aber ich habe die gleiche Ausnahme, egal was (und keine Protokollquelle erstellt wird), auch ohne den MySQL-Teil. Ich habe die EventLog-Berechtigungen auf meinem Computer überprüft.

Es scheint, dass die Ausnahme ausgelöst wird, sobald ich etwas anderes "grundlegenden" C# -Code verwende (wann immer ich versuche, eine andere DLL zu laden).

+0

Der 'CheckConnexion' wird im' NextButtonClick' Event Handler aufgerufen. Wenn ich eine zweite Funktion hatte, ohne 'MySql.Data' zu verwenden, funktioniert es. Der bloße Hinweis scheint nicht das Problem zu sein. – tvarnier

+0

Mit 'File.WriteAllLines' wird die Funktion ohne den Verweis auf' MySql.Data' aufgerufen, protokolliert und gibt korrekt zurück. Der, der 'MySql.Data' verwendet, schlägt immer noch auf die gleiche Weise fehl, ohne etwas zu protokollieren. – tvarnier

+0

Die 'MySql.Data'-DLL wird aufgrund der Referenz in das bin-Verzeichnis von' MyDll' kopiert. Das gesamte Verzeichnis wird in den Abschnitt "[Dateien]" importiert, wie in meinem ursprünglichen Beitrag beschrieben. Ich kann sehen, wie sowohl "MySql.Data.dll" als auch "MyDll.dll" im temporären Inno-Setup-Verzeichnis zur Laufzeit extrahiert werden. – tvarnier

Antwort

2

Es gibt wahrscheinlich einen besseren Weg, aber das wird es tun.

Implementieren einer Initialisierungsfunktion (Init hier), die AppDomain.AssemblyResolve handler einrichtet, die in dem Pfad des Haupt (Ausführen) -Anordnung für eine Baugruppe aus:

[DllExport("Init", CallingConvention.StdCall)] 
public static void Init() 
{ 
    AppDomain currentDomain = AppDomain.CurrentDomain; 
    currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler); 
} 

private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args) 
{ 
    string location = Assembly.GetExecutingAssembly().Location; 
    AssemblyName name = new AssemblyName(args.Name); 
    string path = Path.Combine(Path.GetDirectoryName(location), name.Name + ".dll"); 
    if (File.Exists(path)) 
    { 
     return Assembly.LoadFrom(path); 
    } 
    return null; 
} 

Import es dem Inno Setup:

procedure Init(); external '[email protected]:MyDll.dll stdcall setuponly'; 

Und rufen Sie es vor dem Aufruf der Funktion, die die Abhängigkeit benötigt (CheckConnexion).


Eine andere Lösung könnte sein:
Embedding DLLs in a compiled executable


Btw, keine Notwendigkeit für die loadwithalteredsearchpath Flagge. Es hat keine Auswirkungen auf .NET Assemblies imo.

+0

Das hat den Trick gemacht! Ich sehe die Logik hier, aber das ist eine Schande, dass wir das tun müssen, besonders unter Windows ^^. Es scheint idd, dass das Flag 'loadwithalteredsearchpath' nicht für .NET Assembly funktioniert. Danke vielmals ! – tvarnier

+0

Fertig :) Btw, ich habe damals versucht, die DLL einzubetten. Es funktionierte auf meinem Entwicklungscomputer, aber nicht auf dem CI-Server, da Costura für .NET 4.5.x kompiliert wurde und es scheint, dass .NET 4 und 4.5-Compiler Schnittstellenunterschiede aufweisen. Deshalb musste ich direkt auf MySql.Data verweisen. Diese Problemumgehung ist jedoch eine großartige Lösung für einfache Architektur. – tvarnier

Verwandte Themen