Laden...

C# Codedom: Zur Laufzeit erstelle .exe wirft BadImageFormatException beim Laden von benötigter DLL

Erstellt von cence99 vor 10 Jahren Letzter Beitrag vor 10 Jahren 3.863 Views
Hinweis von herbivore vor 10 Jahren

Originaltitel war: "C# Codedom - Zur Laufzeit .exe generieren"

C
cence99 Themenstarter:in
8 Beiträge seit 2012
vor 10 Jahren
C# Codedom: Zur Laufzeit erstelle .exe wirft BadImageFormatException beim Laden von benötigter DLL

Hallo liebe Community,

Ich war lange inaktiv im Forum, bin aber wieder da 😁 👍.

Ich bin dabei eine sehr kleine Game Engine in C# zu schreiben, und mache dabei Gebrauch von Windows Forms und SFML .Net 2.1.

Situation:

Ich habe einen Button, der das "erstellte" Spiel in der game engine zu einer .exe kompilieren soll. Das ist im Prinzip nur die 'CSharpCodeProvider'-Klasse die mittels eines string-Arrays (worin jeder string einer in Visual Studio erstellten .cs Datei entspricht) die C# code enthalten soll eine .exe zaubert.
Ein wichtiger Parameter sind die Verweise (references), auch ein string-Array.
Da ich das Zeichnen im Spiel (und in der Engine) mit SFML .Net mache, muss ich auch auf die SFML .dll Dateien verweisen.
Das sieht dann so aus:


            // The references
            string[] references = new string[]
            {
                // C# 
                "System.dll",
                // SFML
                "sfmlnet-audio-2.dll",
                "sfmlnet-graphics-2.dll",
                "sfmlnet-window-2.dll"
            };

Das sind relative Pfade zu den .dll Dateien, welche ich auch in den Ordner der generierten .exe kopiere. Ich habe es auch mit absoluten Pfaden versucht.

Aber hier kommt das Problem:

In dem Code den ich für das Game (die zu generierende .exe) angegeben habe, mache ich Gebrauch von einigen Klassen der sfmlnet-window-2.dll Datei, um ein Fenster zu erzeugen, wenn man das Spiel öffnet.
Wie auch immer, die .exe generiert sich, keine Fehler, nur wenn ich das Programm starte, öffnet sich eine Konsole und mir wird ein Fehler angezeigt, dass die Assembly sfmlnet-window-2 nicht gefunden worden konnte.
"Das Programm funktioniert nicht mehr" teilt mir Windows mit und ich muss es schließen.

Keine Ahnung wieso das passiert, deshalb bin ich hier. 🙂
Er findet also die verwiesenen SFML .dll Files nicht..
Hoffe jemand versteht was davon und kann mir weiterhelfen.

Der Code ist simpel, hier ist die Methode die ich zum Generieren der .exe verwende:


        private static void BuildGame(string[] codefiles, string[] references, string outputName)
        {
            CSharpCodeProvider provider = new CSharpCodeProvider();

            CompilerParameters compilerparams = new CompilerParameters(references, outputName);
            compilerparams.GenerateExecutable = true;
            compilerparams.GenerateInMemory = false;

            CompilerResults results = provider.CompileAssemblyFromSource(compilerparams, codefiles);

            if (results.Errors.HasErrors)
            {
                StringBuilder errors = new StringBuilder("Compiler Errors :\r\n");
                foreach (CompilerError error in results.Errors)
                {
                    errors.AppendFormat("Line {0},{1}\t: {2}\n",
                           error.Line, error.Column, error.ErrorText);
                }
                throw new Exception(errors.ToString());
            }

            MessageBox.Show("Successfully built game!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

Parameter Erklärung:
"codeFiles" sind die bereits angesprochenen "Dateien" die den C# Code beinhalten.

"references" sind die oben gezeigten Verweise auf .dll Dateien.

"outputName" ist der Name der zu generierenden .exe Datei.

Vielen Dank im Vorraus,
Mike

# # #

# ## # #

# # # # #

# # # #

# # # #

# # ## #

# # # #

5.657 Beiträge seit 2006
vor 10 Jahren

Hi cence99,

wenn ich das Programm starte, öffnet sich eine Konsole und mir wird ein Fehler angezeigt, dass die Assembly sfmlnet-window-2 nicht gefunden worden konnte.

Da hast du doch den Fehler schon ziemlich genau eingegrenzt. Wo liegt denn die DLL? Wenn die Laufzeitumgebung die DLL benötigt, schaut sie in den Ordner der EXE-Datei oder im GAC nach. Also mußt du dafür sorgen, daß sie an einem dieser Orte zu finden ist.

Christian

Weeks of programming can save you hours of planning

C
cence99 Themenstarter:in
8 Beiträge seit 2012
vor 10 Jahren

Hi MrSparkle,

Das Problem ist ja eben, dass diese sich im Ordner der .exe befinden..
Kann also irgendwas nicht stimmen.
Die Namen sind richtig angegeben und stimmen überein.

welche ich auch in den Ordner der generierten .exe kopiere. Ich habe es auch mit absoluten Pfaden versucht.

# # #

# ## # #

# # # # #

# # # #

# # # #

# # ## #

# # # #

16.806 Beiträge seit 2008
vor 10 Jahren

Die Fehlermeldung heisst doch im Original, dass die DLL oder eine Abhängigkeit nicht gefunden wird.
Nimm Dir den Dependency Walker zur Hand, schau nach, welche DLL tatsächlich nicht gefunden wird und wo diese gesucht wird.

C
cence99 Themenstarter:in
8 Beiträge seit 2012
vor 10 Jahren

Es werden wohl irgendwelche Windows .dll Dateien gesucht und manche nicht gefunden.. Aber von SFML steht nirgends was.

# # #

# ## # #

# # # # #

# # # #

# # # #

# # ## #

# # # #

S
145 Beiträge seit 2013
vor 10 Jahren

Füg einfach testweise deine generierten Codedateien einem richtigem Testprojekt hinzu.

Ansonsten könnteste per Reflector, ILSpy, etc. auch mal schauen ob deine Exe richtig erstellt wurde.

Ansonsten schaut mir aber deine referenz angabe ehrlich gesagt zu einfach aus,
habs etwas anders in erinnerung.
Kanns aber jetzt nicht sagen, das entsprechende Projekt hab ich auf arbeit.

Achja, oder du erstellst mal die Exe im speicher und startest diese ausm speicher in deiner VS Umgebung.
(Hab da glaube per Reflection auf die geladene DLL (DLL wars bei mir) zugriffen,
per Activator.CreateInstance dann Startobjekte instanziiert und konnte dann schön debuggen.)

Seh grad:
kannst sein das ev. einfach blos
System.Drawing, System.Windows.Forms, und so in den referenz angaben fehlt

P.S: den oberen teil lass ich jetzt ma stehn, falls irgendwie mit hilft

C
cence99 Themenstarter:in
8 Beiträge seit 2012
vor 10 Jahren

Danke für die Antworten 👍

Ich verstehe wirklich nicht wieso das nicht funktioniert.. ?(

Hier nochmal die vollständige Fehlermeldung die in der Konsole ausgegeben wird:

Fehlermeldung:
Unbehandelte Ausnahme: System.BadImageFormatException: Die Datei oder Assembly "sfmlnet-window-2", Version=2.1.0.0, Culture=neutral PublicKeyToken=null" oder eine Abhängigkeit davon wurde nicht gefunden. Es wurde versucht, eine Datei mit einem falschen Format zu laden.
bei SomeNameSpace.MySFMLProgram.StartSFMLProgram()
bei SomeNameSpace.Program.Main(String[]args)

Wieso System.BadImageFormatException? Welches Image? huh?

Ich habe den Code der zu einer .exe kompliert wird in ein Projekt getan, dort in die Verweise nur System und die SFML Abhängigkeiten gepackt und voilà, in VS 2012 funktioniert es..

Kann mir echt nicht vorstellen was da falsch läuft.

# # #

# ## # #

# # # # #

# # # #

# # # #

# # ## #

# # # #

16.806 Beiträge seit 2008
vor 10 Jahren

Die kurze (Foren-)Suche nach BadImageFormatException sollte Dir sagen, dass es _wahrscheinlich _ein Problem mit x86 / x64 gibt.
[Hinweis] Wie poste ich richtig? 1.1
Und das ist eine ganz andere Fehlermeldung als nur "nicht gefunden". Daher auch hier der Hinweis auf [Hinweis] Wie poste ich richtig? Punkt 5.

Die MSDN sagt dazu (übrigens erster Google Treffer nach BadImageFormatException):

Eine DLL oder eine ausführbare Datei wird als 64-Bit-Assembly geladen, aber sie enthält 32-Bit-Funktionen oder Ressourcen. Es benötigt z. B. COM-Interop oder ruft Methoden in einer 32-Bit-Dynamic Link Library auf.
Um diese Ausnahme zu behandeln, legen Sie die Eigenschaft Zielplattform des Projekts auf x86 (statt x64 oder AnyCPU) fest und kompilieren diese neu.

_Wahrscheinlich _hast Du AnyCPU eingestellt - _oder _aber gibts nen Problem mit einer evtl. nicht vorhandenen aber erforderlichen .NET Version. Du musst Dich den Dlls von SMFL anpassen, was bei C++ DLLs normal ist.
Nutzt Du x86 Dlls -> x86 einstellen. Bei x64 eben x64. AnyCPU ist da i.d.R. tabu.

Aber: es kann immer noch auch an irgendeiner Dll liegen, die von SMFL verwendet wird, diese aber auf den ersten Blick nicht ersichtlich ist - das sagt Dir auch die Fehlermeldung => Abhängigkeiten.
Daher mein Hinweis des Dependency Walkers. Sagt er Warning bei einer DLL kann das meist ignoriert werden, Error sind die interessanten Dinge. Und wenn der sagt, dass er eine DLL braucht und nicht findet, dann stimmt das auch in 99,9999% der Fälle.

C
cence99 Themenstarter:in
8 Beiträge seit 2012
vor 10 Jahren

Bei meinem Engine-Projekt habe ich ja auch x86 eingestellt, sonst füllt er die Fehlerliste mit Warnungen (weil ich die x86 Version von SFML habe). Leider weiß ich nicht (nach einer langen Suche noch immer nicht) wie man die Zielplattform über Codedom einrichtet. Die CSharpCodeProvider-Klasse lässt einem einige Settings als Parameter (Dicitonary<>) angeben. Im Netz fand ich aber nur, dass man dadurch die .Net Version angeben kann.
Ich verzweifle langsam wirklich 🤔.

Weiß jemand noch eine Antwort? 🙁

# # #

# ## # #

# # # # #

# # # #

# # # #

# # ## #

# # # #

S
417 Beiträge seit 2008
vor 10 Jahren

Das Setzen der Platform lässt sich doch leicht ergooglen:
CompilerParameters.CompilerOptions Property und /platform (C# Compiler Options)

Verwendung:

compilerparams.CompilerOptions = "/platform:x86";
C
cence99 Themenstarter:in
8 Beiträge seit 2012
vor 10 Jahren

Vielen Dank allen Antwortlern und Sarc für dieses offensichtliche Problem. 🤔 👍

Jetzt kann ich weiter an der Engine arbeiten. 🙂

# # #

# ## # #

# # # # #

# # # #

# # # #

# # ## #

# # # #