I build a CodeCompileUnit and the following code outputs a C# source code file, a .dll and I can get an instance from the assembly:
TextWriter tw = new IndentedTextWriter(new StreamWriter(filePath + ".cs", false), " ");
provider.GenerateCodeFromCompileUnit(compileUnit, tw, new CodeGeneratorOptions());
tw.Close();
CompilerParameters cp = new CompilerParameters { GenerateInMemory = true, GenerateExecutable = false};
cp.ReferencedAssemblies.Add("MyProgram.exe");
cp.OutputAssembly = filePath + ".dll";
CompilerResults cr = provider.CompileAssemblyFromFile(cp, filePath + ".cs");
MyType instance = (MyType)Activator.CreateInstance(cr.CompiledAssembly.GetTypes()[0]);
So far so good. Now I would like to avoid generating those files:
CompilerParameters cp = new CompilerParameters { GenerateInMemory = true, GenerateExecutable = false};
cp.ReferencedAssemblies.Add("MyProgram.exe");
//cp.OutputAssembly = filePath + ".dll";
CompileResults cr = provider.CompileAssemblyFromDom(cp, compileUnit);
This throws a FileNotFoundException. It looks for a x32savit.dll (or similar) in my \temp folder but it is not there. If I uncomment the OutputAssembly it fails the same but on that path.
It turned out to be an error with namespaces. There is a good example here.
Adding the following code was very helpful while debugging.
string errorText = String.Empty;
foreach (CompilerError compilerError in compilerResults.Errors)
errorText += compilerError + "\n";
Related
I have created a tool that open a c# Winform application, the question is after I made some modification to the files I want to recompile those files programmatically using c#.
You can do it by using CSharpCodeProvider. You can find more information about this class in documentation.
after searching i have use this solution :
String[] csFiles = CopyAllSourceFilesToCLASSESFolder().ToArray();
String[] referenceAssemblies = { "System.dll", "System.Drawing.dll", "System.Windows.Forms.dll", "ICSharpCode.TextEditor.dll", "System.Xml.dll", "System.IO.dll", "System.ComponentModel.dll" , "System.Data.dll" , "System.linq.dll" };
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
ICodeCompiler icc = codeProvider.CreateCompiler();
string Output = "Out.exe";
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters(referenceAssemblies);
//Make sure we generate an EXE, not a DLL
parameters.GenerateExecutable = true;
parameters.OutputAssembly = Output;
CompilerResults results = icc.CompileAssemblyFromFileBatch(parameters, csFiles);
if (results.Errors.Count > 0)
{
foreach (CompilerError CompErr in results.Errors)
{
ErrorTextBox.Text = ErrorTextBox.Text +
"Line number " + CompErr.Line +
", Error Number: " + CompErr.ErrorNumber +
", '" + CompErr.ErrorText + ";" +
Environment.NewLine + Environment.NewLine;
}
}
else
{
//Successful Compile
ErrorTextBox.ForeColor = Color.Blue;
ErrorTextBox.Text = "Success!";
//If we clicked run then launch our EXE
}
Process.Start(Output);
I am trying to do a Visual Studio kind of program, which allows you to type code into a RichTextBox. After pressing F5(Compile), it would compile the code. How would the user compile said code? I know how to use the ConsoleApplication Compiler, but not compiling Windows Forms :(
Could someone help? A code-example is preferable, but at this point, I'll accept ANYTHING!
My current code for Console Apps is this:
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
ICodeCompiler icc = codeProvider.CreateCompiler();
string Output = "MCCACOut.exe";
Button ButtonObject = (Button)sender;
richTextBox201.Text = "";
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
//Make sure we generate an EXE, not a DLL
parameters.GenerateExecutable = true;
parameters.OutputAssembly = Output;
CompilerResults results = icc.CompileAssemblyFromSource(parameters, richTextBox301.Text);
if (results.Errors.Count > 0)
{
richTextBox201.ForeColor = Color.Red;
foreach (CompilerError CompErr in results.Errors)
{
richTextBox201.Text = richTextBox201.Text +
"Line number " + CompErr.Line +
", Error Number: " + CompErr.ErrorNumber +
", '" + CompErr.ErrorText + ";" +
Environment.NewLine + Environment.NewLine;
}
}
else
{
//Successful Compile
richTextBox201.ForeColor = Color.Blue;
richTextBox201.Text = "Success!";
//If we clicked run then launch our EXE
Process.Start(Output);
}
Could anyone convert this to compile WinForms instead of ConsoleApp? :)
I think you have to save your file with .cs extension and invoke a process to compile it using c# compiler csc.exe.
After saving the file, you can compile the code using,
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe [options] filename.cs
Take a look at this for options
You can invoke a process to do this from your IDE.
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe filename.cs";
process.StartInfo = startInfo;
process.Start();
Hope this helps.
Finally, after many, many times of struggling, I got it to work :) With the help of Nishan Chathuranga
string compiledOutput = "Generated.exe";
//COMPILATION WORK
String[] referenceAssemblies = { "System.dll", "System.Drawing.dll", "System.Windows.Forms.dll" };
CodeDomProvider _CodeCompiler = CodeDomProvider.CreateProvider("CSharp");
System.CodeDom.Compiler.CompilerParameters _CompilerParameters =
new System.CodeDom.Compiler.CompilerParameters(referenceAssemblies, "");
_CompilerParameters.OutputAssembly = compiledOutput;
_CompilerParameters.GenerateExecutable = true;
_CompilerParameters.GenerateInMemory = false;
_CompilerParameters.WarningLevel = 3;
_CompilerParameters.TreatWarningsAsErrors = true;
_CompilerParameters.CompilerOptions = "/optimize /target:winexe";//!! HERE IS THE SOLUTION !!
string _Errors = null;
try
{
// Invoke compilation
CompilerResults _CompilerResults = null;
_CompilerResults = _CodeCompiler.CompileAssemblyFromSource(_CompilerParameters, richTextBox1.Text);
if (_CompilerResults.Errors.Count > 0)
{
// Return compilation errors
_Errors = "";
foreach (System.CodeDom.Compiler.CompilerError CompErr in _CompilerResults.Errors)
{
_Errors += "Line number " + CompErr.Line +
", Error Number: " + CompErr.ErrorNumber +
", '" + CompErr.ErrorText + ";\r\n\r\n";
}
}
}
catch (Exception _Exception)
{
// Error occurred when trying to compile the code
_Errors = _Exception.Message;
}
//AFTER WORK
if (_Errors == null)
{
// lets run the program
MessageBox.Show(compiledOutput + " Compiled !");
System.Diagnostics.Process.Start(compiledOutput);
}
else
{
MessageBox.Show("Error occurred during compilation : \r\n" + _Errors);
}
This works like a charm!
I has a question, does CodeDom Compiler can compile c# code with custom configuration such as x64 bit or x86 bit.By default it compiles c# code to .exe with "Any CPU" configuration.
Compiling c# code:
public static string BCS(string[] sources,string[] libs,string outPath,bool exef)
{
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters(libs);
parameters.GenerateExecutable = exef;
parameters.OutputAssembly = outPath;
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, sources);
if (results.Errors.Count > 0)
{
string errsText = "";
foreach (CompilerError CompErr in results.Errors)
{
errsText = "("+CompErr.ErrorNumber +
")Line " + CompErr.Line +
",Column "+CompErr.Column +
":"+CompErr.ErrorText + "" +
Environment.NewLine;
}
return errsText;
}
else
{
return "Success";
}
}
I think,youre understand my question,if not, leave a comment,i will give details.
Try to set CompilerOptions this way
parameters.CompilerOptions = "-platform:anycpu32bitpreferred";
using params from this link
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/platform-compiler-option
P.S. CSharpCodeProvider uses csc.exe
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/command-line-building-with-csc-exe
I am making a c# compiler and my code creates an executable that is automatically created in the startup folder(Working Directory).
Is there any way to change the path in which the EXE is created before creating it.
This code creates an executable in "C:\Users\User\Desktop\CSharp Compiler\CSharp Compiler\bin\Debug"
CSharpCodeProvider csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } });
CompilerParameters parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" }, ProjectName.Text + ".exe", true);
parameters.GenerateExecutable = true;
System.CodeDom.Compiler.TempFileCollection tfc = new TempFileCollection(Application.StartupPath, false);
CompilerResults cr = csc.CompileAssemblyFromSource(parameters, txtcode.Text);
if (cr.Errors.HasErrors)
{
//Do something if there is an error here...
}
else
{
//Start the application if there is no errors
Process.Start(Application.StartupPath + "/" + ProjectName.Text + ".exe");
}
To set the working directory, you need to use the ProcessStartInfo version of Process.Start
It can be as simple as
System.Diagnostics.ProcessStartInfo PSI = new System.Diagnostics.ProcessStartInfo();
PSI.FileName = Application.StartupPath + "/" + ProjectName.Text + ".exe";
PSI.WorkingDirectory = Application.StartupPath;
System.Diagnostics.Process.Start(PSI);
I was experimenting with dynamic class creation at runtime but I get the following error when i run my program at the last line. Does anyone know how to solve this? I tried searching similar problems online but none of the solutions have helped me. Thanks in advance for any help
Could not load file or assembly 'file:///C:\Users\xxxx\AppData\Local\Temp\jelsfwqz.dll' or one of its dependencies. The system cannot find the file specified.
string code2 = "using System;" +
"using System.Collections.Generic;" +
"using System.Linq;" +
"using System.Text;" +
"" +
" public sealed class CustomClass" +
" {" +
" }"
;
// Compiler and CompilerParameters
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
CompilerParameters compParameters = new CompilerParameters();
CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");
// Compile the code
CompilerResults res = codeProvider.CompileAssemblyFromSource(compParameters, code2);
// Create a new instance of the class 'CustomClass'
object myClass = res.CompiledAssembly.CreateInstance("CustomClass");
Fixed code:
string code2 =
" public sealed class CustomClass" +
" {" +
" }"
;
// Compiler and CompilerParameters
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
CompilerParameters compParameters = new CompilerParameters();
CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");
**compParameters.ReferencedAssemblies.Add("System.dll");**
// Compile the code
CompilerResults res = codeProvider.CompileAssemblyFromSource(compParameters, code2);
// Create a new instance of the class 'CustomClass'
object myClass = res.CompiledAssembly.CreateInstance("CustomClass");