Autor Beitrag
KanneM
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26
Erhaltene Danke: 1

Win98, Win XP, Win 7
Java, C#
BeitragVerfasst: Mo 19.03.12 12:07 
Liebe Community,

Ich suche schon lange nach einer (hoffentlich existierenden) Lösung für mein Problem, habe aber nie etwas passendes gefunden:

Ich möchte gerne, dass ein Programm einen C#-Code aus z.B. einer Textdatei einliest und anschließend ausführt (Annahme: Code ist fehlerfrei). Also praktisch ein extrerner Code den man in ein Hauptprogramm integriert, jedoch dann variabel... Existiert so eine Möglichkeit überhaupt oder ist das unlösbar? O.o

Mit freundlichen Grüßen,
Kanne
daeve
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 116
Erhaltene Danke: 3

Windows (XP Pro, 7 Ultimate x64)
C#,WPF,Java,ASP.Net, VS 2010 Ultimate (x86)
BeitragVerfasst: Mo 19.03.12 12:11 
Für was brauchst du den so was ?
gewisse Teile des Codes die anpassbar sein müssen, kann man über ein Konfigurationsfile erledigen...
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 19.03.12 12:21 
Einfach den Code durch den Compiler jagen(siehe z.b. hier)? Der kompilierte Code sollte dann irgendeiner Definition folgen damit du weißt wie das Kompilat dann auszuführen ist. Also zum Beispiel könnten die Klassen in diesem Code eine bestimmtes Interface implementieren nach dem du im Kompilat suchen kannst um dann eine bestimmte Methode an diesem Interface aufzurufen um in auszuführen.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 19.03.12 13:37 
Hallo KanneM,

die von Ralf genannte Möglichkeit nennt sich CodeDOM. Unter Stringwerte in ausführbaren Code umwandeln (sowie Programm, um Programme zu erstellen) habe ich noch weitere Artikel dazu aufgelistet.

Für diesen Beitrag haben gedankt: KanneM
KanneM Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26
Erhaltene Danke: 1

Win98, Win XP, Win 7
Java, C#
BeitragVerfasst: Mo 19.03.12 15:47 
user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
Hallo KanneM,

die von Ralf genannte Möglichkeit nennt sich CodeDOM. Unter Stringwerte in ausführbaren Code umwandeln (sowie Programm, um Programme zu erstellen) habe ich noch weitere Artikel dazu aufgelistet.


Habs mal ausprobiert, klappt wunderbar =)

Nur eins noch: Das direkte einbinden in die aktuelle Anwendung geht nicht, oder? Also quasi: "FuehreAus(string CodeString)"
Ich meine klar, "http://blogs.msdn.com/b/thottams/archive/2006/08/16/701872.aspx" und dann die .exe ausführen lassen geht, aber es wäre doch schöner wenn die Anwendung direkt den String-Code ausführen würde.

MfG,
Kanne
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 19.03.12 16:02 
Zitat:
aber es wäre doch schöner wenn die Anwendung direkt den String-Code ausführen würde.


Bei diesem Code aus deinem Link sollte es doch eigentlich bei dir klingeln was zu ändern wäre um deinem Wunsch nahe zu kommen.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = true;
cp.OutputAssembly = "Result.exe";
cp.GenerateInMemory = false;
CompilerResults cr = provider.CompileAssemblyFromSource(cp, sourcecode);
KanneM Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26
Erhaltene Danke: 1

Win98, Win XP, Win 7
Java, C#
BeitragVerfasst: Mo 19.03.12 16:06 
user profile iconRalf Jansen hat folgendes geschrieben Zum zitierten Posting springen:
Zitat:
aber es wäre doch schöner wenn die Anwendung direkt den String-Code ausführen würde.


Bei diesem Code aus deinem Link sollte es doch eigentlich bei dir klingeln was zu ändern wäre um deinem Wunsch nahe zu kommen.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = true;
cp.OutputAssembly = "Result.exe";
cp.GenerateInMemory = false;
CompilerResults cr = provider.CompileAssemblyFromSource(cp, sourcecode);


Ich denke schon... Bin mir aber nicht sicher, in unseren Vorlesungen sind wir noch nicht so tief eingetaucht.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = false;
//cp.OutputAssembly = "Result.exe";
cp.GenerateInMemory = true;
CompilerResults cr = provider.CompileAssemblyFromSource(cp, sourcecode);


Würde das dann so funktionieren?

LG,
Kanne
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 19.03.12 16:18 
Theoretisch. In den CompilerResults solltest du jetzt deine Assembly finden.
KanneM Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26
Erhaltene Danke: 1

Win98, Win XP, Win 7
Java, C#
BeitragVerfasst: Mo 19.03.12 17:47 
user profile iconRalf Jansen hat folgendes geschrieben Zum zitierten Posting springen:
Theoretisch. In den CompilerResults solltest du jetzt deine Assembly finden.

D.h. ich könnte es jetzt wie aufrufen? Sorry, aber ich bin nochnet so fit in dem Gebiet, arbeite weng vor...
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 19.03.12 20:42 
Nur ein paar Stichworte, da ich jetzt nicht viel Zeit habe:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
CompilerResults.CompiledAssembly
CreateInstance
GetMethod
Invoke
...


Als Beispiel auf die Schnelle habe ich stackoverflow.com/qu...and-execute-a-method gefunden

Viel Erfolg noch dabei
KanneM Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26
Erhaltene Danke: 1

Win98, Win XP, Win 7
Java, C#
BeitragVerfasst: Di 20.03.12 13:12 
Also ich hab mal weng was durchprobiert, letztenendes endet es immer in einem Fehler... Glaube auch nicht dass ich des richtig angesetzt habe...
Könntest du mir vllt zeigen wie der Code aussehen würde, dann könnte ich mein Projekt bis nächste Woche noch fertig stellen =/

LG,
Kanne
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 20.03.12 14:32 
Hallo KanneM,

machen wir es besser umgekehrt. Du präsentierst deinen bisherigen (kompilierfähigen) Code und dann schauen wir zusammen darauf und geben dir Tipps.
KanneM Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26
Erhaltene Danke: 1

Win98, Win XP, Win 7
Java, C#
BeitragVerfasst: Di 20.03.12 16:22 
Wiegesagt, die Änderung die ich oben gepostet habe ist das was funktioniert, das dann aber zum laufen bringen ist die Schwierigkeit. Ich hab mit Activator.Create... und ... .CreateInstance rumprobiert, ein Assemblyverweis brachte auch nicht das gewünschte Resultat.

Wird wohl noch zu hcoh für mich sein, aber ich will das jetzt wenigstens fertig bekommen =D

-------------------------------------------------------------------------------------------------

EDIT: Hab jetzt nochmal was anderes gefunden:
msdn.microsoft.com/d...ibrary/ms173139.aspx
Hierbei wird wohl aber eine exe Datei geladen, also genau das was ich eigentlich nicht will.
Auch hier
stackoverflow.com/qu...and-execute-a-method
habe ich einiges ausprobiert, aber wie soll ich einen Pfad vom Assembly angeben, wenn doch nur der Code kompiliert wird?

LG
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 21.03.12 18:17 
Hallo KanneM,

was genau willst du denn ausführen? Eine einzelne statische Methode oder aber eine Klasse instantiieren und dann eine Methode davon aufrufen?

Im 2.Link (d.h. den ich auch gepostet habe) sind die entscheidenden Zeilen
ausblenden C#-Quelltext
1:
2:
3:
var instanceOfSomeClass = compilerResults.CompiledAssembly.CreateInstance(className);

instanceOfSomeClass.GetType().GetMethod("DoSomething").Invoke(instanceOfSomeClass, null);

Wobei className dann der Klassenname ist und "DoSomething" die aufzurufende Methode darstellt (beide vom Typ string).
Für eine statische Methode kannst du den ersten Parameter bei Invoke dann auf null setzen.

Wenn das auch nicht hilft, dann poste doch mal, was du genau kompilieren willst (dies muß natürlich eine komplette Klasse inkl. Referenzen sein).
KanneM Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26
Erhaltene Danke: 1

Win98, Win XP, Win 7
Java, C#
BeitragVerfasst: Mi 21.03.12 19:16 
Ich bekomme jetzt noch einen Fehler in der zweiten Zeile von deinem Post:

Zitat:
System.NullReferenceException wurde nicht behandelt.
Message=Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
Source=Test
StackTrace:
bei CodeDomSample.CSharpCodeExample() in C:\Users\XXX\Documents\visual studio 2010\Projects\TestConsole\Test\Program.cs:Zeile 194.
bei CodeDomSample.Main() in C:\Users\XXX\Documents\visual studio 2010\Projects\TestConsole\Test\Program.cs:Zeile 206.
bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ThreadHelper.ThreadStart()
InnerException:

oder
Zitat:
Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.


Der 'externe' Code sieht so aus:
ausblenden C#-Quelltext
1:
String sourcecode = "\nusing System;\npublic class Sample \n{\n    static void Main()\n    {\n        Console.WriteLine(\"This is a test\");\n    }\n}"					

Und die verarbeitende Methode: (genau wie hier: blogs.msdn.com/b/tho...06/08/16/701872.aspx)
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
public void CSharpCodeExample()
    {

        String sourcecode = "\nusing System;\npublic class Sample \n{\n    static void Main()\n    {\n        Console.WriteLine(\"This is a test\");\n    }\n}";
        //String sourcecode = "using System;public class Sample{static void Main(){Console.WriteLine(\"This is a test 2\");Console.ReadLine();}}";
    

        CSharpCodeProvider provider = new CSharpCodeProvider();

        CompilerParameters cp = new CompilerParameters();

        cp.GenerateExecutable = false;

        //cp.OutputAssembly = "Result.exe";

        cp.GenerateInMemory = true;

        CompilerResults cr = provider.CompileAssemblyFromSource(cp, sourcecode);

        if (cr.Errors.Count > 0)
        {

            Console.WriteLine("Errors building {0} into {1}", sourcecode, cr.PathToAssembly);

            foreach (CompilerError ce in cr.Errors)
            {

                Console.WriteLine("  {0}", ce.ToString());

                Console.WriteLine(); 

            }

        }

        else
        {

            Console.WriteLine("Source \n \n {0} \n \n \n built into {1} successfully.", sourcecode, cr.PathToAssembly);

            var instanceOfSomeClass = cr.CompiledAssembly.CreateInstance("Sample");
            instanceOfSomeClass.GetType().GetMethod("Main").Invoke(instanceOfSomeClass, null);
        }

        return;

    }


PS: Habe bei Invoke den Parameter wie du gesagt hast auch auf null gesetzt, ging trotzdem nicht =(

Verstehe ich eigentlich nicht ganz warum das jetzt nicht geht :x

LG,
Kanne
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 21.03.12 19:32 
Deine Methode in der zu kompilierenden Klasse ist statisch (Nebenbei die solltest du auch nicht Main nennen. So sollte nur die Start Methode eines Executables heißen aber nicht irgendeine Methode die man aufrufen kann) Dein Code könnte bereits funktionieren wenn du mal das static weg nimmst. Ansonsten die Methode einfach nicht über eine Instanz aufrufen sondern direkt über die Klasse z.B. in etwa so

ausblenden C#-Quelltext
1:
cr.CompiledAssembly.GetType("Sample").GetMethod("DoSomething", BindingFlags.Public | BindingFlags.Static).Invoke(nullnull);					

Für diesen Beitrag haben gedankt: KanneM
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 21.03.12 19:35 
Hallo,

am besten, du teilst den Code in mehrere Zeilen auf.

Ich nehme an, daß er bei GetMethod("Main"null zurückgibt, da deine Methode nicht public ist.

Also besser darauf abtesten:
ausblenden C#-Quelltext
1:
2:
3:
MethodInfo methodInfo = instanceOfSomeClass.GetType().GetMethod("Main");
if (methodInfo != null)
  methodInfo.Invoke(instanceOfSomeClass, null);

Ansonsten kannst du bei GetMethod auch noch BindingFlags übergeben:
ausblenden C#-Quelltext
1:
2:
BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
MethodInfo methodInfo = instanceOfSomeClass.GetType().GetMethod("Main", BindingFlags);

Am besten du schaust dafür in der MSDN nach...

Für diesen Beitrag haben gedankt: KanneM
KanneM Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26
Erhaltene Danke: 1

Win98, Win XP, Win 7
Java, C#
BeitragVerfasst: Mi 21.03.12 19:58 
Ich habe jetzt mal die Version von Ralf Jansen ausprobiert, funktioniert super! =D
Schau mir jetzt auchmal die anderen Lösungen an und experimentier nochweng mit dem Code damit ich das dann auch komplett alles versteh...

Danke an euch und gerade dich Th69 für die Geduld :D

LG,
Kanne
KanneM Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26
Erhaltene Danke: 1

Win98, Win XP, Win 7
Java, C#
BeitragVerfasst: Mi 21.03.12 20:52 
Ok, neues Problem...
Zitat:
...


EDIT: Hat sich erledigt, habs selbst hinbekommen ;)

Lg
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 21.03.12 21:18 
Einfach mal richtig den Exceptiontext lesen da stehts im Klartext.