Get NameSpace of my Test Class - c#

I have a webdriver solution that has 10 or so projects in it. 1 core assembly/dll that holds all the common methods and 9 other test assemblies that use those methods in their tests.
I need to access an embedded resource for one of those 9 assemblies but I need to do it from inside the core dll. What's the best way to do that.
namespace = webdriver.core
json.cs - reads a json file and returns it as a string
namespace = webdriver.marketplacestest
marketplace1Test.cs - calls one of the methods in json.cs such as getName();
profile.json - holds {"marketplace1" : "Amazon"}
calling an embedded resource from a known namespace is easy. I did that like this:
private static string fromEmbeddedResource(string myNamespace, string myFolder, string fileName)
{
string result;
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(myNamespace + "." + myFolder + "." + fileName))
using (StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
}
return result;
}
As you can see, I just call the following and I have the file as a string
string json = fromEmbeddedResource("WebDriver.Core", "CFG", "pid.json");
It's harder though when the file is embedded in one of my test dlls. Anyone know how I can access or get the assembly's namespace? I tried...
Assembly.GetCallingAssembly().GetTypes();
but it looks like it's pulling types from the WebDriver.Core.dll assembly and not the WebDriver.Marketplace1.dll assembly.

I was able to figure it out. The problem I had was the calling assembly wasn't the correct assembly because I was calling a method in my core dll that called another method in my core dll. I got it working by passing the assembly along but that was expensive. To make things more efficient I modified my static SettingsRepository class that holds the two assemblies in a dictionary. That way I can pass in a string of "core" or "test" and pull the assembly without having to determine if I'm using an executing assembly or calling assembly each time.
private static Dictionary<string, object> _assembly = new Dictionary<string,object>();
public static Assembly getAssembly (string type)
{
return _assembly[type] as Assembly;
}
public static void addAssembly(string myType, Assembly assembly)
{
bool containsKey = _assembly.ContainsKey(myType);
if (!containsKey)
{
_assembly.Add(myType, assembly);
}
}
When I start a test, I always initialize my driver class first so i added the following two sets to that constructor.
Settings.addAssembly("core", Assembly.GetExecutingAssembly());
Settings.addAssembly("test", Assembly.GetCallingAssembly());
Now I can call either assembly I want anytime I want and know which one I'm getting.

Related

How to programmatically create a class library DLL using reflection?

Suppose my code possesses the knowledge about the metadata of a
nonexistent class library "mytest.dll", such as the types in this library, the functions of the types, the parameters and return types of the functions, etc.
How does my code manufacture this DLL using techniques such as reflection?
I know my code can generate the "mytest.cs" text file, then execute the compiler to produce the DLL, then delete the "mytest.cs" file. Just want to know if there are "more advanced" or "cooler" ways to do it.
Thanks.
There are 4 main steps in the process to compile and execute dynamic .net scripts from your application, even really complex scenarios can be simplified in this way:
Generate the code
Compile the script
Load the assembly
Execute the code
Lets generate a simple Hello Generated C# World App right now!:
Create a method that will generate an assembly that has 1 class called HelloWorldApp, this class has 1 method called GenerateMessage it will have X input parameters that will be integers, it will return a CSV string of the arguments that were passed in to it.
This solution requires the following package to be installed:
PM> Install-Package 'Microsoft.CodeAnalysis.CSharp.Scripting'
And will require the following using statements:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
Orchestration
The following method encapsulates the above steps:
private static void GenerateAndExecuteApp(int numberOfParameters)
{
string nameSpace = "Dynamic.Example";
string className = "HelloWorldApp";
string methodName = "GenerateMessage";
// 1. Generate the code
string script = BuildScript(nameSpace, className, methodName, numberOfParameters);
// 2. Compile the script
// 3. Load the Assembly
Assembly dynamicAssembly = CompileScript(script);
// 4. Execute the code
int[] arguments = Enumerable.Range(1, numberOfParameters).ToArray();
string message = ExecuteScript(dynamicAssembly, nameSpace, className, methodName, arguments);
Console.Out.WriteLine(message);
}
Generate the code
You say you already have item 1 sorted out, you can use StringBuilder, T4 templates or other mechanisms to generate the code files.
generating the code itself is its own question if you need help with that.
However, for our demo app, the following would work:
private static string BuildScript(string nameSpace, string className, string methodName, int numberOfParameters)
{
StringBuilder code = new StringBuilder();
code.AppendLine("using System;");
code.AppendLine("using System.Linq;");
code.AppendLine();
code.AppendLine($"namespace {nameSpace}");
code.AppendLine("{");
code.AppendLine($" public class {className}");
code.AppendLine(" {");
var parameterNames = Enumerable.Range(0, numberOfParameters).Select(x => $"p{x}").ToList();
code.Append($" public string {methodName}(");
code.Append(String.Join(",", parameterNames.Select(x => $"int {x}")));
code.AppendLine(")");
code.AppendLine(" {");
code.Append(" return $\"");
code.Append(String.Join(",", parameterNames.Select(x => $"{x}={{{x}}}")));
code.AppendLine("\";");
code.AppendLine(" }");
code.AppendLine(" }");
code.AppendLine("}");
return code.ToString();
}
For an input value of 3, the following code is generated:
using System;
using System.Linq;
namespace Dynamic.Example
{
public class HelloWorldApp
{
public string GenerateMessage(int p0,int p1,int p2)
{
return $"p0={p0},p1={p1},p2={p2}";
}
}
}
Compile the script (and Load it)
These are two discrete steps, however it is easiest to code them together in the same method, for this example we will ignore the generated dll and load the assembly directly into memory, that is generally the more likely use case for this type of scripting scenario anyway.
The hardest element of this is usually the referencing of the relevant dlls. There are a number of ways to achieve this, including loading all the dlls that are in the current executing context, I find a simple way to do this is to access the Assembly reference from the Type reference for the types we want to use inside the dynamic script:
List<string> dlls = new List<string> {
typeof(object).Assembly.Location,
typeof(Enumerable).Assembly.Location
};
Cut a long story short, this method compiles and loads the assembly into memory. It includes some crude compilation error handling, just to demonstrate how to do it:
private static Assembly CompileScript(string script)
{
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(script);
// use "mytest.dll" if you want, random works well enough
string assemblyName = System.IO.Path.GetRandomFileName();
List<string> dlls = new List<string> {
typeof(object).Assembly.Location,
typeof(Enumerable).Assembly.Location
};
MetadataReference[] references = dlls.Distinct().Select(x => MetadataReference.CreateFromFile(x)).ToArray();
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { syntaxTree },
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
// Now we actually compile the script, this includes some very crude error handling, just to show you can
using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);
if (!result.Success)
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
List<string> errors = new List<string>();
foreach (Diagnostic diagnostic in failures)
{
//errors.AddDistinct(String.Format("{0} : {1}", diagnostic.Id, diagnostic.Location, diagnostic.GetMessage()));
errors.Add(diagnostic.ToString());
}
throw new ApplicationException("Compilation Errors: " + String.Join(Environment.NewLine, errors));
}
else
{
ms.Seek(0, SeekOrigin.Begin);
return Assembly.Load(ms.ToArray());
}
}
}
Execute the code
Finally, we can use reflection to instantiate an instance of the new app and then we can obtain a reference to the method and it. The name of the parameters is irrelevant, as long
we pass them through in the correct order:
for this demo the order is sort of irrelevant to, given they are all the same type ;)
private static string ExecuteScript(Assembly assembly, string nameSpace, string className, string methodName, int[] arguments)
{
var appType = assembly.GetType($"{nameSpace}.{className}");
object app = Activator.CreateInstance(appType);
MethodInfo method = appType.GetMethod(methodName);
object result = method.Invoke(app, arguments.Cast<object>().ToArray());
return result as string;
}
Output
The final output from all this for our method with 3 passed into it is:
p0=1,p1=2,p2=3
So that was super crude, you can bypass most of the indirect reflection aspects through the use of Interfaces. If your generated script inherits from types or interfaces that the calling code also has a strong reference to, then ExecuteScript in the above example might look like this:
private static string ExecuteScript(Assembly assembly, string nameSpace, string className)
{
var appType = assembly.GetType($"{nameSpace}.{className}");
object app = Activator.CreateInstance(appType);
if (app is KnownInterface known)
{
return known.GenerateMessage(1,2,3);
}
throw new NotSupportedException("Couldn't resolve known type");
}
The major benefit to using an interface or base class reference is that you can natively set properties or call other methods without having to reflect references to them all or to resort to using dynamic which would work, but becomes a bit harder to debug.
Of course the interface solution is hard to implement when we had a variable number of parameters, so that's not the best example, usually with dynamic scripts you would construct a known environment, say a known class and methods, but you might want to inject custom code into the body of the method.
It's a bit of fun in the end, but this simple example shows that C# can be used as a runtime scripting engine without too much trouble.

C# use DLL functions dynamically

I have two folders, one folder with files and the other one with DLL files, I can not know which or how many DLLs there is inside the DLL files directory (modular use).
Inside every DLL file there is a function that gets FileInfo as parameter.
How could I run all the functions in the DLLs on each file from the files directory?
for example, one of the DLL files:
using System;
using System.IO;
namespace DLLTest
{
public class DLLTestClass
{
public bool DLLTestFunction(FileInfo file)
{
return file.Exists;
}
}
}
Main:
DirectoryInfo filesDir = new DirectoryInfo(path_to_files_Directory);
DirectoryInfo dllsDir = new DirectoryInfo(path_to_dlls_Directory);
foreach(FileInfo file in filesDir.getFiles())
{
//How do I run each one of the dll funtions on each one of the files?
}
Thanks a lot.
C# is static typed language, so if you want to call a specific function from many assemblies, the first step is to define one project with an interface for such a function.
You have to create one project (called ModuleInterface or anything else) with one interface :
public interface IDllTest
{
bool DLLTestFunction(FileInfo file);
}
Then all your Dll projects must have at least one classe which implements this interface :
public class DLLTestClass : IDllTest
{
public bool DLLTestFunction(FileInfo file)
{
return file.Exists;
}
}
Note the implementation of IDllTest above (you have to add a reference to project ModuleInterface).
Finally, in your main project, you have to load all your assemblies from a directory :
DirectoryInfo dllsDir = new DirectoryInfo(path_to_dlls_Directory);
foreach(FileInfo file in dllsDir.getFiles())
{
//Load the assembly
Assembly assembly = Assembly.LoadFile (file.FullName);
//Get class which implements the interface IDllTest
Type modules = assembly.GetTypes ().SingleOrDefault(x => x.GetInterfaces().Contains(typeof(IDllTest)));
//Instanciate
IDllTest module = (IDllTest)Activator.CreateInstance (modules);
//Call DllTestFunction (you have to define anyFileInfo)
module.DLLTestFunction(anyFileInfo);
}
It probably need some adjustments, because i don't have test it !
However I'm sure that it's the steps to follow.
Reference (in french) : http://www.lab.csblo.fr/implementer-un-systeme-de-plugin-framework-net-c/
I hope my English is understandable, feel free to correct me.
Niels proposed a very good solution, with a clear interface. If you don't want to create interface, or if you cann't you could iterate all types and methods to find a known signature:
var definedTypes = Assembly.LoadFile("file").DefinedTypes;
foreach(var t in definedTypes)
{
foreach(var m in t.GetMethods())
{
var parameters = m.GetParameters();
if (parameters.Length ==1 && parameters[0].ParameterType == typeof(FileInfo))
{
var instanse = Activator.CreateInstance(t);
m.Invoke(instanse, new[] { fileInfo });
}
}
}
for this you do need that all classes have a parameterless constructor to instanciate it. As a parameter of Invoke method you give your fileInfo object.
You will have to load the assemblies dynamically find the function in it and call it. All steps are described here

Implicitly creating an instance of a class that is located in a dependent dll

Let's say you are developing a third-party DLL called "ThirdParty.dll" which has a class called JustTryToInstantiateMe. Let's say your customer has an EXE that has a reference to "ThirdParty.dll" or maybe the EXE doesn't have a reference to "ThirdParty.dll" but the EXE can find "ThirdParty.dll" in the PATH if somehow requested. You have no control over the EXE as you are the vendor for the "Thirdparty.dll" and you can only modify what the DLL does. Your customer, the one writing the EXE, agrees to either make a reference to your DLL or put your DLL in the PATH. Nothing more.
Is there a way to instantiate JustTryToInstantiateMe when running the EXE without explicitly using new or invoking a static/Shared method/field/property?
Maybe just using the static/Shared constructor somehow? Maybe on AssemblyLoad() event? Maybe using the registry? a startup process? Looking for ideas...
The nearest way I know how to do this is to dynamically load the assembly and then invoke a method from an instance of a class that you create.
Here is a template in c# for the code:
//add using for system.reflection
String className = "[NAME OF CLASS WITH FULL NAMESPACE GOES HERE]";
String methodName = "[METHOD NAME GOES HERE]"
String dllPath = "[FILE PATH FOR DLL GOES HERE]";
Assembly assembly = Assembly.LoadFile(dllPath);
Type type = assembly.GetType(className);
MethodInfo method = type.GetMethod(methodName);
object context = Activator.CreateInstance(type);
//optionally set up parameters here
object[] parameters = new object[0];
String result = (String) method.Invoke(context, parameters);
For example, I could create a class like so (I know, it's VB, but what follows after is C#.
Public Class my_class
Private hello = "hello world"
Public Function gethello()
Return hello
End Function
End Class
Then after it is compiled, I can use the following code in C# to do what I think it is you are asking:
//using system.reflection
String className = "mytestlibrary.my_class";
String dllPath = "...mytestlibrary.dll";
String methodName = "gethello";
Assembly assembly = Assembly.LoadFile(dllPath);
Type type = assembly.GetType(className);
MethodInfo method = type.GetMethod(methodName);
object context = Activator.CreateInstance(type);
object[] parameters = new object[0];
String result = (String) method.Invoke(context, parameters);
//result is "hello world"
Now, if you want to do the same, but with an already compiled EXE file, then the code is hardly different, but you will need to create a desktop/console application to shell the other executable and properly namespace your DLL. So in YOUR application, add the following code to grab an instance of a class from the DLL referenced inside the EXE.
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
String className = "My_Class";
String ExePath = "[PATH TO EXE]";
String methodName = "gethello";
Assembly assembly = Assembly.LoadFile(ExePath);
Type type = assembly.GetType(className);
MethodInfo method = type.GetMethod(methodName);
object context = Activator.CreateInstance(type);
object[] parameters = new object[0];
String result = (String) method.Invoke(context, parameters);
It is also possible for you to dynamically load assemblies into the EXE, but that is a bit more tricky, so I will leave it at this for now unless you really need to dynamically load your DLL into the EXE.
From research I found out that the simple answer to this question is that this is not possible. The short answer is that in order for a class in a DLL to be loaded the class needs to be referenced by something. If a DLL were able to self-load itself by virtue of JUST being in the PATH this would bring about all kinds of security issues.

Dynamically load assemblies in ASP.NET 5

I used to have some code which scanned the bin directory of my application for assemblies which weren't loaded in the AppDomain yet and loaded them. It basically looked like:
foreach (var assemblyPath in Directory.GetFiles("path\to\bin", "*.dll"))
{
var inspected = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
Assembly.Load(inspected.GetName());
}
I skipped the try/catch clauses, etc for brevity.
This allowed me to drop assemblies in the bin folder at run-time with implementations for certain interfaces and let the IoC container pick them up automatically. Now with the new Roslyn magic, there are no physical DLL's anymore when debugging. Is there any way to retrieve assembly names, project names or dependency names (in project.json) dynamically.
I guess I have to implement something like this example in the Entropy repo, but I don't know how to implement it for my scenario.
You can use the IAssemblyLoadContextAccessor interface to load ASP.NET 5 class library (.xproj) projects dynamically. The following example code works with Beta 4:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
var assemblyLoadContextAccessor = app.ApplicationServices.GetService<IAssemblyLoadContextAccessor>();
var loadContext = assemblyLoadContextAccessor.Default;
var loadedAssembly = loadContext.Load("NameOfYourLibrary");
}
}
What you are looking for is ILibraryManager implementation which provides access to the complete graph of dependencies for the application. This is already flowed through the ASP.NET 5 DI system. So, you can reach out to it from there.
Sample usage can be found inside RoslynCompilationService.
I solved this issue partly using the ILibraryManager as suggested by #tugberk. I changed the approach a bit which dropped the need of scanning the bin folder for new assemblies. I just want all the loaded assemblies in the current AppDomain.
I injected an instance of the ILibraryManager interface in my type finder class and used the GetReferencingLibraries() method with the name of the core assembly, which is referenced by all the other assemblies in the application.
A sample implementation can be found here, where this is the important part:
public IEnumerable<Assembly> GetLoadedAssemblies()
{
return _libraryManager.GetReferencingLibraries(_coreAssemblyName.Name)
.SelectMany(info => info.Assemblies)
.Select(info => Assembly.Load(new AssemblyName(info.Name)));
}
For .net core users, here is my code for loading assemblies from a specific path. I had to use directives, as it's slightly different for .Net Framework and .Net Core.
In your class header you'll need to declare the using something similar to:
#if NET46
#else
using System.Runtime.Loader;
#endif
And in your function something similar to the following:
string assemblyPath = "c:\temp\assmebly.dll";
#if NET46
Assembly assembly = Assembly.LoadFrom(assemblyPath);
#else
AssemblyLoadContext context = AssemblyLoadContext.Default;
Assembly assembly = context.LoadFromAssemblyPath(assemblyPath);
#endif
Its not ASP.NET but it can be converted easily to asp.net.
bellow if function for loading an assembly, and invoke a method inside a class on that assembly.
private static FormCustomized loadLayout(global::System.String layoutFilename, global::System.String layoutNameSpace)
{
FormCustomized mainForm = default;
Type typeMainLayout = default;
FileInfo layoutFile;
layoutFile = new FileInfo(layoutFilename);
layoutFile.Refresh();
if (!layoutFile.Exists)
{
MessageBox.Show("Layout file not found. You need to reinstall the program");
return default;
}
try
{
Assembly assemblyRaw = Assembly.LoadFrom(layoutFilename);
AssemblyLoadContext context = AssemblyLoadContext.Default;
Assembly assembly = context.LoadFromAssemblyPath(layoutFilename);
Type typeMainLayoutIni = assembly.GetType(layoutNameSpace + ".initializeLayoutClass");
Object iniClass = Activator.CreateInstance(typeMainLayoutIni, true);
MethodInfo methodInfo = typeMainLayoutIni.GetMethod("AssembliesToLoadAtStart");
enVars.assemblies = (Dictionary<string, Environment.environmentAssembliesClass>)methodInfo.Invoke(iniClass, default);
typeMainLayout = assembly.GetType(layoutNameSpace + ".mainAppLayoutForm");
mainForm = Activator.CreateInstance(typeMainLayout, enVars) as FormCustomized;
}
catch (Exception ex)
{
return default;
}
return default;
}

Effect of LoaderOptimizationAttribute

I have written a small piece of code regarding the dynamic loading of assemblies and creating class instances from those assemblies, including an executable, a test lib to be dynamically loaded and a loader library to load dynamic assembly into a new Appdomain. Loader library is referenced by both executable and the dynamic library.
//executable
[System.STAThreadAttribute()]
[System.LoaderOptimization(LoaderOptimization.MultiDomain)]
static void Main(string[] args)
{
AppDomainSetup domainSetup = new AppDomainSetup()
{
ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
LoaderOptimization = LoaderOptimization.MultiDomain
};
AppDomain childDomain = AppDomain.CreateDomain("MyDomain", null, domainSetup);
Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString());
Console.WriteLine(childDomain.SetupInformation.LoaderOptimization.ToString());
byte[] assembly = null;
string assemblyName = "CSTestLib";
using (FileStream fs = new FileStream(assemblyName+".dll",FileMode.Open))
{
byte[] byt = new byte[fs.Length];
fs.Read(byt,0,(int)fs.Length);
assembly = byt;
}
object[] pararmeters = {assemblyName,assembly};
string LoaderAssemblyName = typeof(AssemblyLoader).Assembly.FullName;
string LoaderClassName = typeof(AssemblyLoader).FullName;
AssemblyLoader assloader = (AssemblyLoader)childDomain.CreateInstanceAndUnwrap(LoaderAssemblyName,LoaderClassName , true, BindingFlags.CreateInstance, null, parameters, null, null);
object obj = assloader.Load("CSTestLib.Class1");
object obj2 = assloader.Load("CSTestLib.Class2");
AppDomain.Unload(childDomain);
Console.ReadKey();
}
//Dynamic Lib
using System;
namespace CSTestLib
{
public class Class1 :MarshalByRefObject
{
public Class1() { }
}
public class Class2 : MarshalByRefObject
{
public Class2() { }
}
}
//Loader Library
using System;
namespace LoaderLibrary
{
public class AssemblyLoader : MarshalByRefObject
{
string assemblyName;
public AssemblyLoader(string assName, byte[] ass)
{
assemblyName = assName;
AppDomain.CurrentDomain.Load(ass);
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + " " + AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString());
}
public object Load(string className)
{
object ret = null;
try
{
ret = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName, className);
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
return ret;
}
}
}
Here I set LoaderOptimizationAttribute on main() method but AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString(); says it is NotSpecified Why?
The differences between MultiDomain and MultiDomainHost is not so clear to me. Is MultiDomainHost for only GAC assemblies? For my situation which is more suitable?
According to this
JIT-compiled code cannot be shared for
assemblies loaded into the load-from
context, using the LoadFrom method of
the Assembly class, or loaded from
images using overloads of the Load
method that specify byte arrays.
So how can I detect if an assembly is loaded domain-neutral or not? How can assure I it is loaded domain-neutral?
This attribute has only an effect if you precompile your assemblies with NGen to speed up a warm start of your application. When you specify MultiDomain or MultiDomainHost you enable the usage of precompiled (ngenned) assemblies. You can verify this with Process Explorer where you can look at the list of loaded modules.
This is one of the biggest startup time savers if your application consists of several executable instances which share assemblies. This enables .NET to share the code pages between processes which in turn saves real memory (one assembly exists only once in the physical memory but it is shared between one or more processes) and prevents JITing the same code over and over again in each process which takes time at the cost that the generated code is a little less efficient as it could be when it would be compiled with the regular JIT which can use more dynamic data to generate the most efficient code.
In your example you load the assembly into a byte array which is located in the managed heap and increases your private byte count. This makes it impossible to share data between processes. Only read only pages which have a counterpart on your hard disc can be shared between processes. This is the reason why the attribute has no effect. If you are after a factor 2 of warm startup performance this is the attribute you were seeking for. For anything else it is not relevant.
Now back to your original question:
It is set but when you start your application under a debugger this MultiDomain attribute is ignored. When you start it outside of a debugger you will get the expected results.
Yes MultiDomainHost does enable AppDomain neutrality only for signed assemblies all others are not shared.
Code sharing can only happen when it is precompiled. The real question is: How to check if the assembly is precompiled? I do it with Process Explorer by looking at the list of loaded modules. When my loaded assembly shows up with a path to the Native Image cache and an .ni extension I am sure the precompiled image is beeing used. You can check this also with fuslogvw when you set the radio button to Native Images to check why a native images was not used by the runtime.

Categories

Resources