I am aware of a class called AssemblyBuilder, and I would have thought I could use it to pass a folder containing C# source files, or pass a single C# source file to it in order to compile the source into an assembly (.dll) which can then be referenced in a config file.
I'm aware of csc.exe which can compile C#, and I'm effectively looking for a way to replicate this dynamically.
I couldn't figure out how to use AssemblyBuilder, or whether this is the wrong class to be using, or whether I should be doing something similar to the following:
http://support.microsoft.com/kb/304655
Can you point me in the right direction please.
You might want to look into CodeDomProvider
Example snippet:
CompilerParameters parms = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true,
IncludeDebugInformation = false
};
parms.ReferencedAssemblies.Add("System.dll");
parms.ReferencedAssemblies.Add("System.Data.dll");
CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");
return compiler.CompileAssemblyFromSource(parms, source);
Warning: assemblies built dynamically in this fashion won't be handled by the garbage collector.
Related
I'm actually integrating the amazing RoslynPad into a WinForms application and working damn well.
The point of the integration is allowing the user to type in some C# code so it can be used in a future.
Thing is I'm interested on "capping" the user so he could just use some System or even LinQ functions. I don't want to allow the user to think he is allowed to use System.IO and others. Of course I can't prevent him/her typing System.IO.File.Delete, but will surely help if the System.IO's Assembly is not loaded into the RoslynPad's IntelliSense.
The source code typed by the user is going to be compiled locally before being saved into the DB. I'm adding just a few and necessary Assemblies for the compilation, so if System.IO it won't compile, of course.
As I explained, I just want to cap the Intellisense, so they don't think they have access to almost the whole .NET Framework.
EDIT: Added the actual implementation actually done. I'm loading "RoslynPad.Roslyn.Windows" and "RoslynPad.Editor.Windows" assemblies to the editor.
private RoslynCodeEditor _editor;
private void InitializeEditor(string sourceCode)
{
if (string.IsNullOrWhiteSpace(sourceCode))
sourceCode = string.Empty;
_editor = new RoslynCodeEditor();
var workingDirectory = Directory.GetCurrentDirectory();
var roslynHost = new RoslynHost(additionalAssemblies: new[]
{
Assembly.Load("RoslynPad.Roslyn.Windows"),
Assembly.Load("RoslynPad.Editor.Windows")
});
_editor.Initialize(roslynHost, new ClassificationHighlightColors(), workingDirectory, sourceCode);
_editor.FontFamily = new System.Windows.Media.FontFamily("Consolas");
_editor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#");
_editor.FontSize = 12.75f;
elementHost1.Child = _editor;
this.Controls.Add(elementHost1);
}
You can use pass a RoslynHostReferences instance to the RoslynHost constructor, and decide which assemblies and namespaces are imported by default.
You could use the same logic as Default, just remove System.IO.Path from the type list.
Note that System.IO is not an assembly, but rather a namespace, which is in the core library, so there's no simple way to completely remove it.
I need to compile C# code at run-time. I'm using the code like this:
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.ReferencedAssemblies.Add("MyLibrary.dll"); // File Path on Hard Drive
...
But I want to use the libraries loaded on memory instead of their file addresses. Is it possible?
If it is an assembly that isn't generated in-memory only, you could use:
parameters.ReferencedAssemblies.Add
( typeof(ClassInAssemblyYouWantToAdd).Assembly.Location
);
Or:
parameters.ReferencedAssemblies.Add
( Assembly.Load("Full.Qualified.Assembly.Name").Location
);
The Location property has the path to the assembly loaded.
It has to have a hard copy of the assembly, and not just something in memory, so you can't just use generated assemblies for that. You could save the in-memory generated assemblies to disk first if you need to use them.
I can execute a C# source from PowerShell and a PowerShell source from C#.
The question is, How can I execute a C# source from a C# program without compiling with csc.exe?
Yes. This is explicitly catered for in the .net framework using the CodeDom class namespace. http://msdn.microsoft.com/en-us/library/650ax5cx(v=vs.110).aspx System.CodeDom and System.CodeDom.Compiler.
(from the documention)
CSharpCodeProvider provider = new CSharpCodeProvider();
// Build the parameters for source compilation.
CompilerParameters cp = new CompilerParameters();
// Add an assembly reference.
cp.ReferencedAssemblies.Add( "System.dll" );
// Generate an executable instead of
// a class library.
cp.GenerateExecutable = true;
// Set the assembly file name to generate.
cp.OutputAssembly = exeFile;
// Save the assembly as a physical file.
cp.GenerateInMemory = false;
// Invoke compilation.
CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile);
I realise this does use the compiler internally, which is something the OP wished to avoid, but I can't see any reason not to use this to .
I need shell32 in my program to create a shortcut.
This is my code:
var compiler = new CSharpCodeProvider();
var Params = new System.CodeDom.Compiler.CompilerParameters
{
GenerateExecutable = true,
OutputAssembly = outputName,
ReferencedAssemblies = {
"System.dll",
"System.Core.dll",
"System.Windows.Forms.dll",
"System.Drawing.dll",
#"C:\Windows\System32\Shell32.dll"
}
};
Doing this, I get an error:
Metadata file C:\Windows\System32\Shell32.dll could not be opened. An attempt was made to load a program with incorrect format.
Found nothing while searching.. I wasn't even sure what to search for :/
How would I go about doing this?
Shell32.dll (Windows file systems don't care about case, so "s" or "S" shouldn't matter) is not a .NET assembly and thus can't be treated as such.
If you want to call functions exported from non-.NET libraries, you should use the DllImportAttribute.
I had the same problem and just solved it.
Add the following to your referenced Assemblies list:
ReferencedAssemblies.Add("Interop.Shell32.dll");
I want to Load and Create Assemblies during runtime and someone told me to use the Namespace System.Reflection.Assembly and System.Reflection.Emit.
Only reference I found was on the msdn, but it´s not as good to work with it when you don´t know where and how to start. I already googled but I didn´t find any useful tutorials/samples/references.
Can someone explain the functionality to me or give me some samples/tutorials?
http://msdn.microsoft.com/en-us/library/saf5ce06.aspx
public static void CompileScript(string source)
{
CompilerParameters parms = new CompilerParameters();
parms.GenerateExecutable = true;
parms.GenerateInMemory = true;
parms.IncludeDebugInformation = false;
parms.ReferencedAssemblies.Add("System.dll");
// Add whatever references you might need here
CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");
CompilerResults results = compiler.CompileAssemblyFromSource(parms, source);
file.move(results.CompiledAssembly.Location,"c:\myassembly.dll");
}
One possible way to create assembly from a source file(s) is simply run CSC (C# command line compiler) passing in source files and references as arguments. Manual IL generation is likely way too advanced, especially if you want to build assemblies from code provided by someone else.
To load - use Assembly.Load.