I have the following problem:
I am compiling C#-code at runtime using the CSharpCodeProvider in Microsoft.CSharp. The created application runs perfectly, if I double-click on the generated file.
If, however, I am loading my created assembly with Assembly.Load and invoking the entrypoint-method with Assembly.Load("...").EntryPoint.Invoke(null, null), I get a NullReferenceException.
The NullReferenceException is referring to the value of the .EntryPoint-Property.
When I debug the variable containing the loaded Assembly, VisualStudio shows the following:
Larger image
The error is in German and means The value of "local" or argument "asm" is not available in this instruction pointer and can therefore not be determined. It may have been removed during optimization.
I want to add at this point that my generated assembly is not optimized (I also added the compiler argument /optimize-, which prevents optimization.)
I performed an other test to determine the error source by trying this Code:
Assembly asm = Assembly.LoadFile(Assembly.GetExecutingAssembly().Location);
asm.EntryPoint.Invoke(null, argv);
This code is also throwing a NullReferenceException at the line containing the Invoke-call.
Does someone here know, where this error is coming from and I can solve it?
Thank you very much :)
EDIT:
The entrypoint-method is defined as follows:
namespace tmp
{
public static class Program
{
[STAThread]
public static void Main(string[] argv)
{ ... }
}
}
I also tried to invoke it with .EntryPoint.Invoke(null, new string[]{"test", "argument"}), but it didn't solve the problem :/
EDIT #2: I found my error - please look at the comment from #Hans Passant and myself for the soulution
~closed~
Copy and paste from Hans Passant's comment:
// Get your assembly.
Assembly asm = Assembly.LoadFile(Assembly.GetExecutingAssembly().Location);
// Get your point of entry.
MethodInfo entryPoint = asm.EntryPoint;
// Invoke point of entry with arguments.
entryPoint.Invoke(null, new object[] { new string[] { "arg1", "arg2", "etc" } } );
If you want to access an assembly from an embedded resource, use this snippet:
byte[] yourResource = Properties.Resources.YourResourceName;
Assembly asm = Assembly.Load(yourResource);
what if you try something like this will it work?
Assembly asm = Assembly.LoadFile(Assembly.GetExecutingAssembly().Location);
MethodInfo myMethod = asm.EntryPoint;
myMethod.Invoke(null, args);
assuming that that you know the method you want to invoke
Related
Demorepo:
https://github.com/gabbersepp/csharp-dynamic-replace-class
How to use:
Checkout
Compile
Delete TestLib.dll & TestLib.pdb from console/bin/Debug
Execute console.exe through cmd
Old SO post:
Replace existing class definition at runtime with newly created type
Given:
A class in a lib:
namespace Test.TestLib
{
public class Class1
{
}
}
And a second class which creates an instance of it:
namespace console
{
public class AnotherClass
{
public void Create()
{
new Class1();
}
}
}
And a console app that calls create:
static void Main(string[] args)
{
//...
new AnotherClass().Create();
}
Please keep in mind that only Class1 is in an extra lib. The other two classes are in the same.
What I want to do:
Replace the Assembly at runtime:
AssemblyName dynamicAssemblyName = new AssemblyName("TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
dynamicAssembly =
AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
var dynamicModule = dynamicAssembly.DefineDynamicModule("TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
But I want not provide the type at this time. Instead I use:
AppDomain.CurrentDomain.TypeResolve += CurrentDomain_TypeResolve;
private static Assembly CurrentDomain_TypeResolve(object sender, ResolveEventArgs args)
{
Console.WriteLine("resolve type");
if (args.Name.Contains("TestLib"))
{
dynamicModule.DefineType("Test.TestLib.Class1", TypeAttributes.Class | TypeAttributes.Public).CreateType();
return dynamicAssembly;
}
return null;
}
Problem:
The event is not called when the line new AnotherClass().Create(); is executed. Instead an exception is thrown:
System.TypeLoadException: Der Typ "Test.TestLib.Class1" in der
Assembly "TestLib, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null" konnte nicht geladen werden
something like:
System.TypeLoadException: The type "Test.TestLib.Class1" in the
assembly "TestLib, Version = 1.0.0.0, Culture = neutral,
PublicKeyToken = null" could not be loaded
Please have a look into the repo for a full example.
//Edit:
The demo project is written with VS2019 für .net461. I think the main concepts are the same for dotnet core. Let me know if you'd rather work with dotnet core so I can provide the project for both platforms.
//Edit2:
I debugged into the IL Code and saw, that everything runs fine until the constructor of Class1 is called:
So personally I don't think that the event handler is plugged into too late as stated by Bruno.
The official documentation states, that this event is called if the assembly is unknown:
https://learn.microsoft.com/de-de/dotnet/api/system.appdomain.typeresolve?view=netframework-4.8
The TypeResolve event occurs when the common language runtime is
unable to determine the assembly that can create the requested type
I did not read that before. Hopefully someone can help me :-)
//Edit3 - possible solution:
A workaround could be, to create the types based on a list of class names. To not loose compile safety, I can use nameof which produces no IL code. An example can be found in the repo in the branch resolveType-solution1 . But of course, not the solution I am looking for :-(
I am not 100% sure but I think I figured out what is going on.
When running your code, your main is evaluated by the JIT before being executed. This results in an attempt to load AnotherClass and it's dependecies (as everything is very likely to be inlined in the end because it's very small).
This means that you won't have the opportunity to run this code before .net tries to find your type:
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
AppDomain.CurrentDomain.TypeResolve += CurrentDomain_TypeResolve;
I managed to bypass this limitation by not mentionning the class in your main by replacing:
new AnotherClass().Create();
by:
var type = Type.GetType("AnotherClass");
var method = type.GetMethod("Create");
var instance = type.GetConstructor(new Type[] { }).Invoke(new object[0]);
method.Invoke(instance, new object[0]);
The trick is deferring the load of the type after your callbacks have been plugged in the AppDomain. By using reflection I mask the Types really used to the JIT until this code is actually called.
Take away: you don't really know when your type will be loaded (in fact as soon as JIT reads code mentioning your type). This means you have to plug your callback as soon as possible and defer as much as possible the inclusion of code mentioning your type.
calling Type.GetType("Test.TestLib.Class1"); would invoke AppDomain.TypeResolve but not AppDomain.AssemblyResolve, not sure why though
I am trying to get the executing assembly version in C# 3.0 using the following code:
var assemblyFullName = Assembly.GetExecutingAssembly().FullName;
var version = assemblyFullName .Split(',')[1].Split('=')[1];
Is there another proper way of doing so?
Two options... regardless of application type you can always invoke:
Assembly.GetExecutingAssembly().GetName().Version
If a Windows Forms application, you can always access via application if looking specifically for product version.
Application.ProductVersion
Using GetExecutingAssembly for an assembly reference is not always an option. As such, I personally find it useful to create a static helper class in projects where I may need to reference the underlying assembly or assembly version:
// A sample assembly reference class that would exist in the `Core` project.
public static class CoreAssembly
{
public static readonly Assembly Reference = typeof(CoreAssembly).Assembly;
public static readonly Version Version = Reference.GetName().Version;
}
Then I can cleanly reference CoreAssembly.Version in my code as required.
In MSDN, Assembly.GetExecutingAssembly Method, is remark about method "getexecutingassembly", that for performance reasons, you should call this method only when you do not know at design time what assembly is currently executing.
The recommended way to retrieve an Assembly object that represents the current assembly is to use the Type.Assembly property of a type found in the assembly.
The following example illustrates:
using System;
using System.Reflection;
public class Example
{
public static void Main()
{
Console.WriteLine("The version of the currently executing assembly is: {0}",
typeof(Example).Assembly.GetName().Version);
}
}
/* This example produces output similar to the following:
The version of the currently executing assembly is: 1.1.0.0
Of course this is very similar to the answer with helper class "public static class CoreAssembly", but, if you know at least one type of executing assembly, it isn't mandatory to create a helper class, and it saves your time.
using System.Reflection;
{
string version = Assembly.GetEntryAssembly().GetName().Version.ToString();
}
Remarks from MSDN http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getentryassembly%28v=vs.110%29.aspx:
The GetEntryAssembly method can return null when a managed assembly has been loaded from an unmanaged application. For example, if an unmanaged application creates an instance of a COM component written in C#, a call to the GetEntryAssembly method from the C# component returns null, because the entry point for the process was unmanaged code rather than a managed assembly.
Product Version may be preferred if you're using versioning via GitVersion or other versioning software.
To get this from within your class library you can call System.Diagnostics.FileVersionInfo.ProductVersion:
using System.Diagnostics;
using System.Reflection;
//...
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var productVersion = FileVersionInfo.GetVersionInfo(assemblyLocation).ProductVersion
This should do:
Assembly assem = Assembly.GetExecutingAssembly();
AssemblyName aName = assem.GetName();
return aName.Version.ToString();
I finally settled on typeof(MyClass).GetTypeInfo().Assembly.GetName().Version for a netstandard1.6 app. All of the other proposed answers presented a partial solution. This is the only thing that got me exactly what I needed.
Sourced from a combination of places:
https://msdn.microsoft.com/en-us/library/x4cw969y(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/2exyydhb(v=vs.110).aspx
I have a program with a Managed Executable as a resource,
when I try to load the exe using reflection with the following code:
byte[] file = Properties.Resources.ExeName;
Assembly assembly = Assembly.Load(file);
// search for the Entry Point
MethodInfo method = assembly.EntryPoint;
if (method != null)
{
// create an instance of the Startup form Main method
object handle = assembly.CreateInstance(method.Name);
// invoke the application starting point
method.Invoke(handle, null);
}
The assembly I try to load is a valid Managed assembly compiled against .NET Framework 2.0 having the following instruction:
MessageBox.Show("Some Text");
//other stuff goes here
The problem is when I run the application I don't get any MessageBox.Show ("Message") dialog, I tried putting breakpoints in the code everything works fine until it reaches the instruction:
method.Invoke(handle, null);
Once I Step Over here, nothing happens, it neither give any error or exception not it freezes the Editor (VS 2017 Community Edition).
I tried loading other Managed Assemblies, it works fine (provided the assemblies are complied against the same .NET Framework Version (2.0)).
Can anyone point out what possible could be the reason why is the desired exe not executed as expected.
Assembly.EntryPoint is the method that is the entry point for an assembly which will be, even in a Windows Forms project be the Main method. Because this is returning a method, you cannot call Assembly.CreateInstance on it as this is used to create an instance of a Type (which in the case of the Main method is probably called Namespace.For.Project.Program.
You also need to ensure that you're passing the correct number of parameters to the method you're calling, in the second parameter to the call to method.Invoke. In a simple console application, the Main method has a signature of:
static void Main(string[] args)
This means that you need to pass one parameter in, an array of strings. Putting this all together you get:
byte[] file = Properties.Resources.ExeName;
Assembly assembly = Assembly.Load(file);
// search for the Entry Point
MethodInfo method = assembly.EntryPoint;
if (method != null)
{
// Get the type that implements the EntryPoint method
var implementingType = method.DeclaringType;
// Call the EntryPoint method, passing in an empty array of strings as its parameters
method.Invoke(implementingType, new object[] { new string[] { } });
}
When I've created the assembly that is referenced by Properties.Resources.Exename as a "simple" console application (targeting .net Framework 2.0) with the following for the Main method:
static void Main(string[] args)
{
MessageBox.Show("Message " + args == null ? "NULL" : "NOT NULL " + args.Length);
}
Running the program pops a message box with the text "NOT NULL 0" in it, indicating that the parameter has been passed through and is an empty array, which is what I was expecting to see.
As a followup to this question I have now come to the problem of being able to get the Type of a type that is defined by the user in his own solution. Using the standard mscorlib types, everything works.
The question is very easy: how can I get this type from an assembly that I will only know at runtime?
As described in the comments here:
Also, what do you mean by "extracting the type"? You mean getting the Reflection type? There's no good helper, partly because (typically) you can never assume the type you're compiling against is creatable at runtime. There's a strong (and often overlooked) distinction between "compile time" and "run time", and it's rare to bridge them.
Or here on the previous question:
Well, so getting a Type for TypeInfo, naming issues aside, is a tricky problem. It assumes you have an assembly that can be loaded and found. When you do a build, the compiler might be loading reference assemblies that themselves can't be loaded as "normal" assemblies. Even if they are, you might have to hook AppDomain.AssemblyResolve to locate your references, and whatever assembly you built.
"Build" and "runtime" are really different domains, and crossing from one to the other is poorly defined, at best. I assume here that you really need a System.Type because you're using some other reflection API, or trying to then load that type and execute code from it.
I have followed the approach as laid out here and implemented it as such in my Analyzer:
private static Dictionary<string, Assembly> _assemblies = new Dictionary<string, Assembly>();
var containingAssembly = semanticModel.GetSymbolInfo(argument)
.Symbol
.ContainingAssembly;
if (!_assemblies.TryGetValue(containingAssembly.ToString(), out Assembly result))
{
var newAssembly = Assembly.Load(containingAssembly.ToString());
_assemblies.Add(containingAssembly.ToString(), newAssembly);
}
var currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += ResolveAssemblies;
private Assembly ResolveAssemblies(object sender, ResolveEventArgs args)
{
_assemblies.TryGetValue(args.Name, out Assembly result);
return result;
}
But this hasn't made a difference, I keep getting
The User Diagnostic Analyzer 'DiagnosticTools.Collections.ElementaryMethodsNotOverriden.ElementaryMethodsNotOverridenAnalyzer' threw an exception with message 'Could not load file or assembly 'RoslynTester, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.'.
Using fuslogvw.exe gives me this log information which boils down to
LOG: All probing URLs attempted and failed.
After searching for the .dll and .exe version in a few subfolders of /Common7/IDE/.
As context to clarify why I'm doing this: I want to check every type that is used in a collection and verify that it overrides both Equals and GetHashCode. To determine this I have a "classic" reflection extension method that checks this for me:
public static bool IsOverridden(this MethodInfo method)
{
return method.GetBaseDefinition().DeclaringType != method.DeclaringType;
}
So should Roslyn have a way to verify this itself that would make it so that I don't have to use classic reflection at all, then this would also be fine.
Update:
When I use this code as provided by MSDN, I get an "invalid parameter" exception inside Visual Studio but fuslogvw still shows a "file not found" error message. What causes this discrepancy?
private Assembly ResolveAssemblies(object sender, ResolveEventArgs args)
{
Assembly MyAssembly, objExecutingAssemblies;
string strTempAssmbPath = "";
objExecutingAssemblies = Assembly.GetExecutingAssembly();
AssemblyName[] arrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies();
foreach (AssemblyName strAssmbName in arrReferencedAssmbNames)
{
if (strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(",")) == args.Name.Substring(0, args.Name.IndexOf(",")))
{
strTempAssmbPath = #"C:\Users\Jeroen\Documents\Visual Studio 2013\Projects\RoslynTester\RoslynTester\bin\Debug\" + args.Name.Substring(0, args.Name.IndexOf(",")) + ".exe";
break;
}
}
MyAssembly = Assembly.LoadFrom(strTempAssmbPath);
return MyAssembly;
}
I'm assuming you've already found out (programmatically) which class are contained in your collection. You don't really need reflection to accomplish what you want. With Roslyn you can check if a class overrides the Equals method with this SyntaxWalker:
public class FindOverrides : CSharpSyntaxWalker
{
public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
{
base.VisitMethodDeclaration(node);
if (node.Identifier.Text == "Equals"
&& node.Modifiers.Any(m => m.Text == "override"))
{
// found an override of Equals()
}
}
}
To (blindly) check every method of every type in a given solution it can be used like this:
var syntaxRoots =
from project in solution.Projects
from document in project.Documents
select document.GetSyntaxRootAsync().Result;
foreach (var root in syntaxRoots)
new FindOverrides().Visit(root);
There is at least one omission (if that's a valid case for you): my code above won't find if a base class of a given type is overriding Equals().
I am using System.Web.Helpers.Json to deserialize some JSON into dynamic in NET 4. The following line fails with this error: TypeInitializationException: Attempt by method 'System.Web.Helpers.Json..cctor()' to access method 'System.Web.Helpers.Json.CreateSerializer()' failed.
var json = Json.Decode(response);
The response is lengthy but valid JSON. What could be the matter here? I have tried LINQPad with a short handcrafted JSON and it worked. Is this a configuration issue of some sort?
[EDIT]
Here is the actual sample JSON. It appears the content is pretty much irrelevant. When this is run in a brand new Console application or LINQPad, it works as expected. But if you try to run the same code from a brand new Windows Forms application, it barfs with the above error.
var json = Json.Decode("{\"r\":{\"0\":{\"id\":\"2\"},\"1\":{\"id\":\"33\"}}}");
[EDIT2]
Actually, it turns out this has nothing to do with project types. The exception is thrown if the project is being debugged. If it is simply run, the exception does not occur. Strange, eh?
I forgot about this question and I found my answer in the meantime. I think it was somewhere on Microsoft's Connect site but I am not sure. So let's share it now.
Basically, in order to workaround this problem you need to make sure "Enable the Visual Studio hosting process" is unchecked in your project's settings under Debug. I am not sure why it's happening but this is definitely a way to "fix" it. I stopped searching for answers once I found out about this. It was good enough for me.
This can also happen if you are running in a partial trust.
Check the exception description here for possible reasons.
I don't know if this will apply to you, since you are not running in a web context, but this is what that link describes:
This exception is thrown in situations such as the following:
A private, protected, or internal method that would not be accessible from normal compiled code is accessed from partially
trusted code by using reflection.
A security-critical method is accessed from transparent code.
The access level of a method in a class library has changed, and one or more assemblies that reference the library have not been
recompiled.
There is problem in the inbuilt json class.
If you want to achieve this in alternate way, please use the below code:
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new DynamicJavaScriptConverter[] { new DynamicJavaScriptConverter() });
var result = WrapObject(serializer.DeserializeObject(value)); // here you will have result.
private object WrapObject(object value)
{
IDictionary<string, object> values = value as IDictionary<string, object>;
if (values != null)
{
return new DynamicJsonObject(values);
}
object[] arrayValues = value as object[];
if (arrayValues != null)
{
return new DynamicJsonArray(arrayValues);
}
return value;
}
Further to Roland's answer: some assembly mismatches listed can be fixed in the AssemblyInfo.cs file.
The offending line in my AssemblyInfo was this:
[assembly: AllowPartiallyTrustedCallers]
Removing this allowed me to access the public property (on a public class) that I was trying to set from another assembly that had dynamically loaded this assembly.