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
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!
So I would like to compile a whole folder of .cs files and then create a DLL file and then use that DLL in my project on runtime.
I searched the internet and found out CSharpCodeProvider can help me in this.
But what got me confused is that most of the example on this site showed how to read one single file, not a folder as whole.
So I am assuming that my folder containing the .cs files will be linked together.
Example Files:
File: TestMain.cs
class TestMain
{
public static void Main(string[] args)
{
Test t = new Test();
t.Hello();
}
}
File: Test.cs
public class Test
{
public void Hello()
{
Console.Write(#"Hello");
}
}
Any guidance will be well appreciated.
Ok So after searching and guidance here is my working code:
public static Assembly CompileAssembly(string[] sourceFiles, string outputAssemblyPath)
{
var codeProvider = new CSharpCodeProvider();
var compilerParameters = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = false,
OutputAssembly = outputAssemblyPath
};
// Add CSharpSimpleScripting.exe as a reference to Scripts.dll to expose interfaces
//compilerParameters.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
var result = codeProvider.CompileAssemblyFromFile(compilerParameters, sourceFiles); // Compile
if (result.Errors.Count > 0)
{
MessageBox.Show(#"Error Occured");
}
else
{
return result.CompiledAssembly;
}
return null;
}
Basically, You can use CodeDom.Compiler to compile the dll, i wrote somethinglike this long back then use Reflection later to reference it dynamically
//dot net compiler
using System;
using System.CodeDom.Compiler;
using System.IO;
namespace IndiLogix.dotCompiler
{
class dotCompiler
{
FileInfo sourceFile;// = new FileInfo(sourceName);
CodeDomProvider provider = null;
bool compileOk = false;
// Compile Executable
public bool CompileExecutable(String sourceName)
{
sourceFile = new FileInfo(sourceName);
I_GetProvider(sourceFile);
if (sourceFile.Extension.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == ".CS")
{
provider = CodeDomProvider.CreateProvider("CSharp");
//return "CSharp";
}
if (provider != null)
{
// Format the executable file name.
// Build the output assembly path using the current directory
// and _cs.exe or _vb.exe.
String exeName = String.Format(#"{0}\{1}.exe",
System.Environment.CurrentDirectory,
sourceFile.Name.Replace(".", "_"));
string dllName = String.Format(#"{0}\{1}.dll", System.Environment.CurrentDirectory, sourceFile.Name.Replace(".", "_"));
CompilerParameters cp = new CompilerParameters();
// Generate an executable instead of a class library.
cp.GenerateExecutable = true;
// Specify the assembly file name to generate.
cp.OutputAssembly = exeName;
// Save the assembly as a physical file.
cp.GenerateInMemory = false;
// Set whether to treat all warnings as errors.
cp.TreatWarningsAsErrors = false;
// Invoke compilation of the source file.
CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceName);
string temp;
if (cr.Errors.Count > 0)
{
// Display compilation errors.
temp = sourceName + "\n" + cr.PathToAssembly;
foreach (CompilerError ce in cr.Errors)
{
temp += "\nError:" + ce.ToString();
}
System.Windows.Forms.MessageBox.Show(temp, "dotCompiler Error:", System.Windows.Forms.MessageBoxButtons.OK);
}
else
{
// Display a successful compilation message.
//Console.WriteLine("Source {0} built into {1} successfully.",sourceName, cr.PathToAssembly);
System.Windows.Forms.MessageBox.Show("Solution build sucessfully..\n\n" + sourceName + "\n" + cr.PathToAssembly,"dotCompiler:)",System.Windows.Forms.MessageBoxButtons.OK);
}
// Return the results of the compilation.
if (cr.Errors.Count > 0)
{
compileOk = false;
}
else
{
compileOk = true;
}
}
return compileOk;
}
private void I_GetProvider(FileInfo sourceFile)
{
// Select the code provider based on the input file extension.
if (sourceFile.Extension.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == ".CS")
{
provider = CodeDomProvider.CreateProvider("CSharp");
}
else if (sourceFile.Extension.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == ".VB")
{
provider = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("VisualBasic");
}
else
{
//Console.WriteLine("Source file must have a .cs or .vb extension");
//_Notify("Error:", "Source file must have a .cs or .vb extension", ToolTipIcon.Error);
System.Windows.Forms.MessageBox.Show(
"Source file must have *.cs or *.vb extension", "dotCompiler Error",
System.Windows.Forms.MessageBoxButtons.OK);
}
}
private string I_GetProvider_RetStr(FileInfo sourceFile)
{
// Select the code provider based on the input file extension.
if (sourceFile.Extension.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == ".CS")
{
provider = CodeDomProvider.CreateProvider("CSharp");
return "CSharp";
}
else if (sourceFile.Extension.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == ".VB")
{
provider = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("VisualBasic");
return "VisualBasic";
}
else
{
//Console.WriteLine("Source file must have a .cs or .vb extension");
//_Notify("Error:", "Source file must have a .cs or .vb extension", ToolTipIcon.Error);
return "Source file must have *.cs or *.vb extension";
}
}
public bool CompileDll(String sourceName)
{
sourceFile = new FileInfo(sourceName);
I_GetProvider(sourceFile);
if (provider != null)
{
// Format the executable file name.
// Build the output assembly path using the current directory
// and _cs.exe or _vb.exe.
String exeName = String.Format(#"{0}\{1}.exe",
System.Environment.CurrentDirectory,
sourceFile.Name.Replace(".", "_"));
string dllName = String.Format(#"{0}\{1}.dll", System.Environment.CurrentDirectory, sourceFile.Name.Replace(".", "_"));
CompilerParameters cp = new CompilerParameters();
// Generate an executable instead of a class library.
cp.GenerateExecutable = false;
// Specify the assembly file name to generate.
cp.OutputAssembly = dllName;
// Save the assembly as a physical file.
cp.GenerateInMemory = false;
// Set whether to treat all warnings as errors.
cp.TreatWarningsAsErrors = false;
// Invoke compilation of the source file.
CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceName);
string temp;
if (cr.Errors.Count > 0)
{
// Display compilation errors.
temp = "compiling " + sourceName + " to " + cr.PathToAssembly;
foreach (CompilerError ce in cr.Errors)
{
temp += "\nError:" + ce.ToString();
}
System.Windows.Forms.MessageBox.Show(temp, "dotCompiler Error:", System.Windows.Forms.MessageBoxButtons.OK);
}
else
{
// Display a successful compilation message.
//Console.WriteLine("Source {0} built into {1} successfully.",sourceName, cr.PathToAssembly);
System.Windows.Forms.MessageBox.Show("Solution build sucessfully..\n\n" + sourceName + "\n" + cr.PathToAssembly, "dotCompiler:)", System.Windows.Forms.MessageBoxButtons.OK);
}
// Return the results of the compilation.
if (cr.Errors.Count > 0)
{
compileOk = false;
}
else
{
compileOk = true;
}
}
return compileOk;
}
}
}
string sourceCode = #"
public class Test
{
public void Hello()
{
Console.Write(#'Hello');
}
}";
var compParms = new CompilerParameters{
GenerateExecutable = false,
GenerateInMemory = true
};
var csProvider = new CSharpCodeProvider();
CompilerResults compilerResults =
csProvider.CompileAssemblyFromSource(compParms, sourceCode);
object typeInstance =
compilerResults.CompiledAssembly.CreateInstance("Test");
MethodInfo mi = typeInstance.GetType().GetMethod("Hello");
mi.Invoke(typeInstance, null);
Console.ReadLine();
I am working in c# 4.0, i want to generate an executable file dynamically, so i used Code Dome, but when i executes it open in console and after then my form displays, i want to generate winform executable file. How can i achieve my aim. the code is below :
string Code = #"
using System;
using System.Windows.Forms;
namespace CSBSS
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
public class Form1 : Form
{
}
}
";
CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");
string tempFolder = #"..\DynamicOutput";
string Output = System.IO.Path.Combine(tempFolder, #"CSBSS.exe");
if (!System.IO.Directory.Exists(tempFolder))
{
System.IO.Directory.CreateDirectory(tempFolder);
}
else
{
if (System.IO.File.Exists(Output)) System.IO.File.Delete(Output);
}
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
parameters.TempFiles = new TempFileCollection(tempFolder, false);
//Make sure we generate an exe.
parameters.GenerateExecutable = true;
parameters.GenerateInMemory = false;
parameters.OutputAssembly = Output;
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, Code);
string OutputMsg = "";
if (results.Errors.Count > 0)
{
string msgDescr = "";
foreach (CompilerError CompErr in results.Errors)
{
msgDescr += "Line number " + CompErr.Line +
", Error Number: " + CompErr.ErrorNumber +
", '" + CompErr.ErrorText + ";" +
Environment.NewLine + Environment.NewLine;
}
OutputMsg = #"Error occured while generating executable file, please check following internal error
" + msgDescr;
//return false;
}
else
{
OutputMsg = "Executable file has been generated successfully.";
}
Specify the output type to be a Windows application by using the CompilerOptions:
parameters.CompilerOptions = "/target:winexe";
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");