Autor Beitrag
VampireSilence
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109
Erhaltene Danke: 5


C# (VS 2008 Express), PHP/MySQL, Windows XP
BeitragVerfasst: Di 10.05.11 17:19 
Ich sitze gerade an einem Programm, das kleine Autostart-Programme erstellen soll. Diese sollen dann auf eine CD gespeichert und per Autorun.inf aufgerufen werden und nen kleines "Hallo, ich bin foobar" ausspucken.

Das mit der INI war verglichen zum Rest nen Klacks (erledigt => kann ich erstellen).

Nun soll aber die *.exe erstellt werden, die im Grunde genommen nur eine anfängliche MessageBox.Show(string myText) ausführen soll, wobei "myText" beim Erstellen definiert und dann in die *.exe übergeben werden soll. Würde man das manuell erstellen, wäre das also nur eine Zeile, aber warum einfach, wenns auch kompliziert geht ? :P
Jedenfalls: Danach soll noch ggf. ein Bild angehangen werden können, am besten komprimiert (Zip-Class gefunden => kann ich erstellen) und dann als Hintergrundgrafik (Splash) dargestellt werden (Form.BorderDings = none, also auch kein Problem).

Ein Anwendungsbeispiel:
Eine CD wird eingelegt, die Bilder, Videos und Texte enthält und als Autostart, meldet sie sich mit einem Bild und dem Text "Herzlichen Glückwunsch zum Dr.-Titel von AB und XY". Und mein Programm soll sowas nun erstellen können.

Die Frage, die jetzt noch bleibt: Wie erstelle ich also quasi einen Compiler ? Gibt es sowas wie ein php-eval()-Äquivalent, mit dem ich das umsetzen könnte ? Oder ist sowas sehr kompliziert und ich sollte es lieber lassen ? ^^"

mfg
- VampireSilence
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 10.05.11 19:15 
Hallo,

mittels CodeDOM kann man aus .NET heraus Assemblies (d.h. auch EXE-Dateien) generieren lassen. Die zugehörige Klasse lautet: CSharpCodeProvider (bzw. VBCodeProvider für VB.NET) aus dem Microsoft.CSharp-Namensbereich.

Du kannst dir auch mal das Beispielprogramm www.codeproject.com/KB/cs/cscompiler.aspx ansehen, d.h. mittels weniger Code-Zeilen ist dies simpel umzusetzen.

Viel Erfolg!

P.S. Ich habe noch drei weitere Beispiele gefunden:
www.codeproject.com/...cs/MiniCompiler.aspx
www.codeproject.com/...icCompileAndRun.aspx
www.codeproject.com/...ode_Generation1.aspx (kleines Tutorial)
VampireSilence Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109
Erhaltene Danke: 5


C# (VS 2008 Express), PHP/MySQL, Windows XP
BeitragVerfasst: Mi 11.05.11 01:43 
Erstmal vielen Dank für die schnelle Hilfe ! Bin auch schon ein ganzes Stück weiter.

Habe jetzt erstmal klein angefangen, mit der MessageBox. Bin aber hier schon auf ein Problem gestoßen, und zwar ist beim erstellten Programm die Dosbox im Hintergrund sichtbar, obwohl ich eine AssemblyInfo mit [assembly: ComVisible(false)] angehangen habe. Muss das auf nem speziellen Weg eingebunden werden, oder was mache ich falsch ?

Mein Code bisher:

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:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
            CSharpCodeProvider _CodeProvider = new CSharpCodeProvider();

            String[] referenceAssemblies = { "System.dll""System.Drawing.dll""System.Data.dll""System.Windows.Forms.dll" };
            string _AssemblyName = "newAssembly.exe";

            CompilerParameters _CompilerParameters = new CompilerParameters(referenceAssemblies, _AssemblyName);
            
            _CompilerParameters.GenerateExecutable = true;
            _CompilerParameters.GenerateInMemory = false;

            String[] CSharpSourceCode =
            {
                // ASSEMBLY INFORMATIONS
                "using System.Reflection;\r\n" +
                "using System.Runtime.CompilerServices;\r\n" +
                "using System.Runtime.InteropServices;\r\n" +

                "// Allgemeine Informationen über eine Assembly werden über die folgenden \r\n" +
                "// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,\r\n" +
                "// die mit einer Assembly verknüpft sind.\r\n" +
                "[assembly: AssemblyTitle(\"program\")]\r\n" +
                "[assembly: AssemblyDescription(\"\")]\r\n" +
                "[assembly: AssemblyConfiguration(\"\")]\r\n" +
                "[assembly: AssemblyCompany(\"\")]\r\n" +
                "[assembly: AssemblyProduct(\"program\")]\r\n" +
                "[assembly: AssemblyCopyright(\"Copyright ©  2011 by VampireSilence\")]\r\n" +
                "[assembly: AssemblyTrademark(\"\")]\r\n" +
                "[assembly: AssemblyCulture(\"\")]\r\n" +

                "// Durch Festlegen von ComVisible auf \"false\" werden die Typen in dieser Assembly unsichtbar \r\n" +
                "// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von \r\n" +
                "// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf \"true\" fest.\r\n" +
                "[assembly: ComVisible(false)]\r\n" +

                "// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird\r\n" +
                "[assembly: Guid(\"e24b4c01-8c2f-4d1c-bbca-037c321f6514\")]\r\n" +

                "// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:\r\n" +
                "//\r\n" +
                "//      Hauptversion\r\n" +
                "//      Nebenversion \r\n" +
                "//      Buildnummer\r\n" +
                "//      Revision\r\n" +
                "//\r\n" +
                "// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern \r\n" +
                "// übernehmen, indem Sie \"*\" eingeben:\r\n" +
                "// [assembly: AssemblyVersion(\"1.0.*\")]\r\n" +
                "[assembly: AssemblyVersion(\"1.0.0.0\")]\r\n" +
                "[assembly: AssemblyFileVersion(\"1.0.0.0\")]\r\n",

                // MAIN CODE
                "using System;\r\n" +
                "using System.Collections.Generic;\r\n" +
                "using System.ComponentModel;\r\n" +
                "using System.Data;\r\n" +
                "using System.Drawing;\r\n" +
                "using System.Text;\r\n" +
                "using System.Windows.Forms;\r\n" +

                "namespace Test\r\n" +
                "{\r\n" +
                "   static class Program\r\n" +
                "   {\r\n" +
                "       /// <summary>\r\n" +
                "       /// Der Haupteinstiegspunkt für die Anwendung.\r\n" +
                "       /// </summary>\r\n" +
                "       [STAThread]\r\n" +
                "       static void Main()\r\n" +
                "       {\r\n" +
                "           Application.EnableVisualStyles();\r\n" +
                "           Application.SetCompatibleTextRenderingDefault(false);\r\n" +
                "           Application.Run(new Form1());\r\n" +
                "       }\r\n" +
                "   }\r\n" +
                "  partial class Form1\r\n" +
                "    {\r\n" +
                "        /// <summary>\r\n" +
                "        /// Erforderliche Designervariable.\r\n" +
                "        /// </summary>\r\n" +
                "        private System.ComponentModel.IContainer components = null;\r\n" +

                "        /// <summary>\r\n" +
                "        /// Verwendete Ressourcen bereinigen.\r\n" +
                "        /// </summary>\r\n" +
                "        /// <param name=\"disposing\">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>\r\n" +
                "        protected override void Dispose(bool disposing)\r\n" +
                "        {\r\n" +
                "            if (disposing && (components != null))\r\n" +
                "            {\r\n" +
                "                components.Dispose();\r\n" +
                "            }\r\n" +
                "            base.Dispose(disposing);\r\n" +
                "        }\r\n" +

                "        #region Vom Windows Form-Designer generierter Code\r\n" +

                "        /// <summary>\r\n" +
                "        /// Erforderliche Methode für die Designerunterstützung.\r\n" +
                "        /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.\r\n" +
                "        /// </summary>\r\n" +
                "        private void InitializeComponent()\r\n" +
                "        {\r\n" +
                "            this.SuspendLayout();\r\n" +
                "            // \r\n" +
                "            // Form1\r\n" +
                "            // \r\n" +
                "            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\r\n" +
                "            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\r\n" +
                "            this.ClientSize = new System.Drawing.Size(292, 268);\r\n" +
                "            this.Name = \"Form1\";\r\n" +
                "            this.Text = \"Form1\";\r\n" +
                "            this.Load += new System.EventHandler(this.Form1_Load);\r\n" +
                "            this.ResumeLayout(false);\r\n" +

                "        }\r\n" +

                "        #endregion\r\n" +
                "    }\r\n" +

                "   public partial class Form1 : Form\r\n" +
                "   {\r\n" +
                "       public Form1()\r\n" +
                "       {\r\n" +
                "           InitializeComponent();\r\n" +
                "       }\r\n" +

                "       private void Form1_Load(object sender, EventArgs e)\r\n" +
                "       {\r\n" +
                "           MessageBox.Show(\"test ! :)\");\r\n" +
                "       }\r\n" +
                "   }\r\n" +
                "}\r\n"

            };

            CompilerResults _CompilerResults = _CodeProvider.CompileAssemblyFromSource(_CompilerParameters, CSharpSourceCode);


Danke nochmal.

mfg
- VampireSilence
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 11.05.11 09:42 
Hallo VampireSilence,

ComVisible hat nichts mit der DOS-Box (Konsolenfenster) zu tun, sondern steuert nur, ob die öffentlichen Member der Assembly auch für Programme auf Basis von Component Object Model (COM) sichtbar und zugreifbar sind (steht aber ja auch in dem Kommentar in deinem Quellcode ;-)).

Du mußt bei den CompilerParameters noch die CompilerOptionen so setzen, daß eine Windows-Anwendung erzeugt wird (und keine Konsolenanwendung):
ausblenden C#-Quelltext
1:
_CompilerParameters.CompilerOptions = "/target:winexe";					

Die kompletten Compileroptionen (für C#) findest du unter: msdn.microsoft.com/d...y%28v=VS.100%29.aspx

P.S. Anstatt hart-codiert den Source als Strings im Programmcode zu setzen, wäre es wohl einfacher diesen in eine Texdatei oder aber als Ressource auszulagern (denn das erspart dir das lästige "in Anführungsstriche setzen, evtl. noch escapen und \r\n zu ergänzen" (wobei letzteres dem Compiler ja völlig egal ist - Whitespaces werden ja eh überlesen ;-)).