-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bad IL format from Memory Stream #39470
Comments
I don't know much about Roslyn, but the use of Try using |
I've used |
It happens specifically when |
This comment has been minimized.
This comment has been minimized.
Can confirm the issue is reproducible, My code is quite similar to that of this:
` Heres my error information: |
Maybe this working example will help. I took the original source above and turned it into a LINQpad snippet ( https://www.linqpad.net - v6.4.4). // Sample Memory Stream Execution
//
// Packages
// Microsoft.CodeAnalysis.CSharp
//
// using Microsoft.CodeAnalysis;
// using Microsoft.CodeAnalysis.CSharp;
// using System.Threading.Tasks;
//
void Main() {
var tree = CSharpSyntaxTree.ParseText(@"
using System;
public class MyClass
{
public static void Main()
{
Console.WriteLine(""Hello World!"");
}
}");
var baseDotNetPath = @"C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.0.0\";
var references = new List<MetadataReference>() {
MetadataReference.CreateFromFile($@"{baseDotNetPath}System.Private.CoreLib.dll"),
MetadataReference.CreateFromFile($@"{baseDotNetPath}\System.dll"),
MetadataReference.CreateFromFile($@"{baseDotNetPath}\System.Console.dll"),
MetadataReference.CreateFromFile($@"{baseDotNetPath}\System.Runtime.dll"),
};
var compilation = CSharpCompilation.Create("MyCompilation",
syntaxTrees: new[] { tree }, references: references);
//Emit to stream
var ms = new MemoryStream();
var emitResult = compilation.Emit(ms);
//Load into currently running assembly. Normally we'd probably
//want to do this in an AppDomain
var ourAssembly = Assembly.Load(ms.GetBuffer());
var type = ourAssembly.GetType("MyClass");
//Invokes our main method and writes "Hello World" :)
type.InvokeMember("Main", BindingFlags.Default | BindingFlags.InvokeMethod, null, null, null);
} |
I've encountered this, a little extra info: in my case, the |
@danielwcarey using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
namespace DotNetLib
{
public static class Lib
{
[StructLayout(LayoutKind.Sequential)]
public struct LibArgs
{
public IntPtr SourceCode;
public int Number;
public int FuncOid;
}
static MemoryStream memStream;
static IDictionary<int, (string, MemoryStream)> funcBuiltCodeDict;
public static int Compile(IntPtr arg, int argLength)
{
LibArgs libArgs = Marshal.PtrToStructure<LibArgs>(arg);
string sourceCode = Marshal.PtrToStringAuto(libArgs.SourceCode);
if (Lib.funcBuiltCodeDict == null)
Lib.funcBuiltCodeDict = new Dictionary<int, (string, MemoryStream)>();
else {
// Code has not changed then it is not needed to build it
try {
Lib.funcBuiltCodeDict.TryGetValue(libArgs.FuncOid,
out (string src, MemoryStream builtCode) pair);
if (pair.src == sourceCode) {
Lib.memStream = pair.builtCode;
return 0;
}
}catch{}
}
SyntaxTree tree = SyntaxFactory.ParseSyntaxTree(sourceCode);
var trustedAssembliesPaths = ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")).Split(Path.PathSeparator);
var neededAssemblies = new[]
{
"System.Runtime",
"System.Private.CoreLib",
"System.Console",
};
List<PortableExecutableReference> references = trustedAssembliesPaths
.Where(p => neededAssemblies.Contains(Path.GetFileNameWithoutExtension(p)))
.Select(p => MetadataReference.CreateFromFile(p))
.ToList();
CSharpCompilation compilation = CSharpCompilation.Create(
"plnetproc.dll",
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
syntaxTrees: new[] { tree },
references: references);
Lib.memStream = new MemoryStream();
Microsoft.CodeAnalysis.Emit.EmitResult compileResult = compilation.Emit(Lib.memStream);
if(!compileResult.Success)
{
Console.WriteLine("\n********ERROR************\n");
foreach(var diagnostic in compileResult.Diagnostics)
{
Console.WriteLine(diagnostic.ToString());
}
Console.WriteLine("\n********ERROR************\n");
return 0;
}
funcBuiltCodeDict[libArgs.FuncOid] = (sourceCode, Lib.memStream);
return 0;
}
public static int Run(IntPtr arg, int argLength)
{
Assembly compiledAssembly;
compiledAssembly = Assembly.Load(Lib.memStream.GetBuffer());
Type procClassType = compiledAssembly.GetType("DotNetLib.ProcedureClass");
MethodInfo procMethod = procClassType.GetMethod("ProcedureMethod");
procMethod.Invoke(null, new object[] {arg, argLength});
return 0;
}
}
} |
@peteraritchie What kind of errors? |
Could be compile errors. Building source code means it's not valid for a time being and could be invalid when compiled. But, typically I see reference-related errors. |
My Code is similar using (var archive = System.IO.Compression.ZipFile.OpenRead(@"Path to ZIP File"))
{
var entry = archive.Entries.Single(e => string.Equals("xxx.dll", e.Name));
var context = new AssemblyLoadContext("Test", true);
using (Stream assemblyStream = entry.Open())
using (MemoryStream ms = new MemoryStream())
{
assemblyStream.CopyTo(ms);
var assembly = context.LoadFromStream(ms);
....
} First I tried directly loading the stream from ZipEntry (which is a Then I changed to first Copy to Using a Then I played a little bit around and finally i changed the code to first set assemblyStream.CopyTo(ms);
ms.Position = 0;
var assembly = context.LoadFromStream(ms); No Exception is thrown. |
Hi, I would recommend reviewing this article explaining runtime assembly creation, specifically the sentence in the Executing Code section that says:
Edit: I have been corrected. Thanks @svick for the correction. |
|
As far as I can see, @lpeixotoo, @TylerBurnett and @BobSilent all experienced issues because, due to a bug in their code, they attempted to load an empty assembly. I think the exception message in that case should be improved, so I opened dotnet/runtime#36814 about that. With that, I think this issue should be closed, since there doesn't seem to be any problem with Roslyn here. |
Bad IL format from Memory Stream
Hello guys,
I'm trying to run a basic compilation sample by
using a docker environment with:
Version: 3.0.100
Commit: 04339c3a26
OS Name: ubuntu
OS Version: 18.04
OS Platform: Linux
RID: ubuntu.18.04-x64
Base Path: /usr/share/dotnet/sdk/3.0.100/
General
I've based myself in this article.
A reproducible repository can be found here.
Sample Code
For a quick follow up, here's my code
Am i doing something wrong?
The text was updated successfully, but these errors were encountered: