Recently I started to use Reflection, Reflection.Emit and Code Dom. The purpose of my coding is to load an assembly (e.g. "C:\Temp\MyAssembly.exe"), read its classes and methods. This has been done however I am interested to save a copy of "MyAssembly.exe" to "MyAssembly.dll". The reason is because I want to instrument the code and make some changes to the methods.
I am aware about how to create new assemblies and save them, but I am not sure if it is possible to "clone" an existing assembly (including all its classes and methods) with extension .exe to .dll.
I will appreciate any advice!
Thanks.
Peter
Simply saving a copy of "MyAssembly.exe" to "MyAssembly.dll" shouldn't be much of a problem (use File.Copy, for example) and doesn't require Reflection or Reflection.Emit.
But, as the comments reveal, the problem is more one of saving a modified copy of "MyAssembly.exe" to a different file name. It is not possible to modify an existing assembly using Reflection.Emit, but you have other options:
you could use a third-party tool such as Cecil or Microsoft CCI to load the assembly, modify it, and save it under a different name;
you could use the IL disassembler and IL assembler included with the .NET framework/SDK to disassemble, then modify, then reassemble your assembly;
in theory, you could probably load the assembly, analyze it via Reflection and emit a completely equivalent new assembly using Reflection.Emit; however, I'd not take that route, as it would be an enormous piece of work to get this right.
Related
Is it possible to extract a class from an assembly created with Reflection.Emit and save it physically to a directory?
I would like to use this manipulation to generate projects dynamically with specific content (classes, methods ...).
Is there a way to save dynamic classes with code without need for an external tool to decompile them?
Yes, as long as you pass in AssemblyBuilderAccess.RunAndSave or AssemblyBuilderAccess.Save when you call AssemblyBuilder.DefineDynamicAssembly. Then you can use the Save method to write it to disk - very useful for running it through Peverify to see what you've done wrong :)
Note that this saves the IL - not C# source code, so you would still need to decompile them. If you want C# source code without decompiling, then you would need to generate C# source code as your origin - presumably passing it through Roslyn or CSharpCodeProvider to get the IL.
Note: not all operations are valid when used in this way - if you are skipping accessibility checks, for example, to access non-public members of types outside of your control. This is allowed in some runtime-only scenarios, but is not reliable in assemblies loaded from disk. Similarly, a lot of things are possible in IL that have no direct C# equivalent.
Going over some legacy code, I ran into piece of code that was using reflection for loading some dll's that their source code was available (they were another project in the solution).
I was cracking my skull trying to figure out why it was done this way (naturally the code was not documented...).
My question is, can you think about any good reason for preferring to load an assembly via reflection rather than referencing it?
Yes, if you have a dynamic module system, where different DLLs should be loaded depending on conditions at runtime. We do this where I work; we do a license check for different optional modules that may be loaded into our system, and then only load the DLLs associated with each module if the license checks out. This prevents code that should never be executed from being loaded, which can both improve performance slightly and prevent bugs.
Dynamically loading DLLs may also allow you to drastically change functionality without changing any source code. The main assembly may for instance set in motion a discovery process where it finds all classes that implement some interface, and chooses which one to use depending on some runtime criterion.
These days you'll typically want to use MEF for this kind of task, but that's only been around since .NET 4.0, so there are probably many codebases out there that do it manually. (I don't know much about MEF. Maybe you have to do this part manually there as well.)
But anyway, the answer to your question is that there certainly are good reasons to dynamically load DLLs using reflection. Whether it applies in your case is impossible to say without more details.
Without knowing you specific project, noone here can tell you why it was done that way in your case.
But the general reasons are:
updateability: You can simply recompile and replace the updated libary instead of having to recompile and replace the whole application.
cooperation: if the interface is clear, that way multiple teams can work together. one for the main application and others for the dlls
reusability: sometimes you need the same functionality in multiple projects, so the same dll can be used again and again
extensability: in some cases you want to be able to later extend your program with plugins that where not present at shipment time. This can be realized using dlls.
I hope this helps you understand some of your setup..
Reason for loading an assembly via reflection rather than referencing it?
Let us consider a scenario, where there are three classes with method DoWork() this method returns string, you are accessing it by checking the condition (strong type).
Now you have two more classes in two different DLL's how would you cope up the change?
1)You can add reference of new DLL's , change the conditional check and make it work.
2)You can use reflection , pass on condition and assembly name at run time, this allows you to add any number of functionality at runttime without any change of code in primary appliation.
I have a .NET DLL that I register with regasm.exe as a Browser Helper Object. I embedded several Win32 resources in the DLL using .res files and /win32 switch to csc.exe.
image.png HTML "image.png"
I am able to access the resources using the res protocol as long as I include the absolute path of the DLL.
res://C:\Path\To\My\Dll\Assembly.dll/image.png
This is rather unfortunate. I would much rather just reference the assembly name as I have seen in many other examples:
res://Assembly.dll/image.png
But this results in an error because the browser can't find the resource.
Ideas?
I think there are a couple things that can be done. First, I believe your assembly needs to be a part of the global assembly cache if you don't want to be forced to use the full path.
Add assembly to global assembly cache.
It's not pretty and you must also keep in mind that a newer build of the DLL will be different from the version in cache. So it would essentially be another extra step to take which would just lead us back to accepting having to put in the full path in the first place.
Second, another solution I believe that works would be to place the DLL in the same directory as the VS utility or the other resources you're trying to use. This could be applicable to multiple different things that one might want to do, but requires manually moving your files around.
Third, you create some custom environmental variables that represent the path that you desire. So instead of typing the full path in the future, you just type your variable.
The third option is my favorite and something that I use for multiple different things I need to accomplish from the command-line.
Using System.Reflection, I can get all methods from a specific class
I need know what are the references to these methods. For example: in Visual Studio, if you want the references of specific object
right click on the object and select "Find All References"
Visual Studio show the references of this selected object
I want make the same, but from code with reflection or another way.
Can I do this?
This cannot be done with reflection. Reflection is a tool for inspecting metadata and assemblies. In order to find all references to a given method / type, you'd need to inspect the underlying IL of an assembly. Reflection only has very limited IL capabilities (simply returns it as a byte array). You'll need to custom inspect that byte stream in order to gather any context about what it's referencing.
That's not something that's directly accessible via runtime reflection on a specific class. You will have to introspect the entire source code tree or resulting IL to determine if any references to a particular method with the same name are the right overload and signature for the method you're trying to find references to.
Furthermore, without additional work, you're never going to find references to a specific method that are themselves invoked via reflection. (This is one reason why obfuscating that kind of code is challenging and error-prone.)
If you're just looking to find the references for informational purposes, Reflector has that feature.
http://www.red-gate.com/products/reflector/
Microsoft released the Common Compiler Infrastructure projects under an open source license. These projects aim to support many compiler-related features, including assembly analysis like you're referring to. The documentation is limited, so you'll need to have a thorough understanding of ECMA-335 (Common Language Infrastructure) to effectively use it for your purposes.
There are no magic code samples here. This is a large and quite complicated task where you'll be on your own most of the way.
I'm writing .NET On-the-Fly compiler for CLR scripting and want to implement next idea: there is a template file with C# code, I want to read it, create an assembly, load it and amplify source on-the-fly. How can I do that?
You can do this with CompileAssemblyFromSource. I've done something simliar in the past, where I augmented some scripts with static class wrappers so they could easily be called. You can see it (or steal from it) here.
To do this, just load your template, add your extra amplifications to the code, and compile it in one shot.
If you want to modify an existing assembly, you will need to use something like Mono.Cecil. It allows you to load and modify as assembly at runtime. There is a CodeProject article using Reflexil, a GPL product based on Cecil, which may help you get some ideas...