How to decompile assembly without have the dependencies - c#

This question is based in (ILSpy, how to resolve dependencies?)
Well, the ILSpy library changed and now we don't have Ast Builder, like the most answers about this.
The instance new ICSharpDecompiler have a overload that can take a ModuleDefinition of Mono.Cecil, but I don't know if this ModuleDefinition is the new "Resolver" for this issue.
In the resume I need to decompile a assembly (C#, .dll) that I don't have the dependecies (dll), I need to read the assembly using CSharpDecompiler decompiler = new CSharpDecompiler(dll.Name + ".dll", new DecompilerSettings()); without have the dependencies, how can I do that?

I got the solution making a simple:
CSharpDecompiler decompiler = new CSharpDecompiler("name.dll", new DecompilerSettings() {ThrowOnAssemblyResolveErrors = false})
This will ignore the dependencies but the types with references will not be read.

Related

What is the 2013 way to load an assembly at runtime?

I want to load several assemblies at runtime from my plugin directory. The core app does not have references to the assemblies beforehand, the assemblies implement an interface given by the core app, thus have a reference to it. I found and article from 2005 explaining exactly what I need to do to make this work.
Currently I have this code, which is basically a LINQ'd version of what you find in the article above:
foreach (
IModule module in
Directory.EnumerateDirectories(string.Format(#"{0}/{1}", Application.StartupPath, ModulePath))
.Select(dir => Directory.GetFiles(dir, "*.dll"))
.SelectMany(files => files.Select(Assembly.LoadFrom)
.SelectMany(assembly => (from type in assembly.GetTypes()
where type.IsClass && !type.IsNotPublic
let interfaces = type.GetInterfaces()
where
((IList) interfaces).Contains(
typeof (IModule))
select
(IModule) Activator.CreateInstance(type))))
)
{
module.Core = this;
module.Initialize();
AddModule(module);
}
So what is the current way to dynamically load plugins/modules/assemblies at runtime?
You might want to look at Microsoft Managed Extensibility Framework also this Tutorial its kinda nice intro.
I'd suggest Managed Extensibility Framework
Alternatively, if you need to load "plugins" with no need to keep a reference, there is also PRISM
Doesn't the roslyn project provide with some helpful things?
http://msdn.microsoft.com/en-us/vstudio/roslyn.aspx
http://www.developerfusion.com/article/143896/understanding-the-basics-of-roslyn/
var scriptEngine = new ScriptEngine();
var session = Session.Create();
scriptEngine.Execute("foo.dll", session);

How to use an DLL load from Embed Resource?

I have a DLL >> System.Data.SQLite.dll
To use it in a normal way > just add it as reference and
using System.Data.SQLite;
then, I can use all the functions inside this DLL.
But, I want to merge my app.exe and this DLL into one single file.
I have tried using ILmerge, but fail. As I know, ILmerge cannot merge unmanage DLL.
So, I tried another method > make the DLL as embbed resource.
I am able to load it as an assembly with the below code:
Stream stm = Assembly.GetExecutingAssembly().GetManifestResourceStream("MyApp.System.Data.SQLite.dll");
byte[] ba = null;
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = stm.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
ba = ms.ToArray();
}
Assembly sSQLiteDLL = Assembly.Load(ba);
but, how am I going to use the functions in SQLiteDLL?
I also tried add the DLL as resource in properties and load it like this:
public Form1()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
InitializeComponent();
}
System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
AppDomain domain = (AppDomain)sender;
if (args.Name.Contains("System_Data_SQLite"))
{
return domain.Load(MyApp.Properties.Resources.System_Data_SQLite);
}
return null;
}
The above explained what I've got so far and I don't know what to do next to use the DLL? I still can't use the functions inside the DLL.
For example, when I type this:
SQLiteCommand cmd = new SQLiteCommand();
The Visual Studio says:
Error 21 The type or namespace name 'SQLiteCommand' could not be found (are you missing a using directive or an assembly reference?)
Can you share your insight? Thanks.
You can embed an assembly AND reference it (in VS) at the same time... for the way you want to use it you need to reference it! Any reason you don't reference the Assembly ?
Using a Type from an embedded Assembly (managed) without referencing it is a bit harder but possible using Reflection etc. - see these links (they include reference material AND some sample code etc.):
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
https://stackoverflow.com/a/57450/847363
http://msdn.microsoft.com/en-us/library/h538bck7.aspx (loads an ssembly from a byte array so there is no need to write that assembly to the filesystem)
http://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettype.aspx
http://www.codeproject.com/Articles/32828/Using-Reflection-to-load-unreferenced-assemblies-a
On embedding managed DLLs you have several options:
use ILMerge (free)
For howto see here and here
OR
use some tool like SmartAssembly (commercial)
it can embed and merge among other things (no need to change your source code)
OR
code that yourself in less than 10 lines (free but minimal source code change)
mark all needed dependencies as "embedded resource" - this way they are included in the EXE file... you need to setup an AssemblyResolve handler which at runtime reads from Resources and returns the needed DLLs to the .NET runtime...
This is not a method to use assemblies loaded in AppDomain.
Please read this article: How to: Load Assemblies into an Application Domain
in short you should call GetMethod() with method name (for example SqlCommand) and then call it via .Invoke() method.

AppDomain.AppendPrivatePath alternative?

I read a LOT of things mostly via google (not here on SO) and didn't find something that answer to my question so I'm asking it here.
What I do want to add to "something" (to an AppDomain I think) so that my code can resolve AT RUNTIME how to Assembly.CreateInstance a specific DLL that is outside of my application's compilation folder.
I really feel like AppDomain is the class to use and AppendPrivatePath sounded like the method to use but it now is "Obsolete"...
msdn suggest to use PrivateBinPath but as far as I understood I have to create a new AppDomain and with my tests, I feel like Assembly.CreateInstance doesn't look for references in my new AppDomain
Some code like :
AppDomainSetup domaininfo = new AppDomainSetup();
domaininfo.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
domaininfo.PrivateBinPath = "D:\\.....\\bin\\Debug\\";
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
AppDomain newDomain = AppDomain.CreateDomain("FrameworkDomain", adevidence, domaininfo);
works, but then, when I try to CreateInstance, I got a TargetInvocation exception
I, too, tried :
Thread.GetDomain().SetupInformation.PrivateBinPath = "D:\\.....\\bin\\Debug\\";
which sounds "special" but good to me, but it doesn't work...
I really feel like I HAVE TO give to D:\\.....\\bin\\Debug\\ path to the current AppDomain but its no longer possible since AppendPrivatePath is Obsolete...
Any help ?
You can resolve additional DLLs yourself on an event the assembly fires to let you know that it cannot find a type.
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += MyResolve;
AppDomain.CurrentDomain.AssemblyResolve += MyResolve;
private Assembly MyResolve(Object sender, ResolveEventArgs e) {
Console.Error.WriteLine("Resolving assembly {0}", e.Name);
// Load the assembly from your private path, and return the result
}
I might be totally of the track what you are actually trying to build but assuming that you want to build a plugin infrastructure where you want to organize plugins in subfolders like this:
\plugins\foo\foo.dll
\plugins\foo\dependency_that_foo_needs.dll
\plugins\bar\bar.dll
\plugins\bar\dependency_that_bar_needs.dll
The problem that you encountered is that that foo.dll fails to load its dependency because the framework does not look in that subdirectory for the assembly to load.
Using the latest preview of the Managed Extensibility Framework (MEF 2 Preview) one can build such things really easy. I assume you could even do that with an earlier version, however earlier versions forced you to use special attributes on your plugins that the most recent version does not depend on any longer.
So, assume that is your plugin contract:
public interface IPlugin
{
string Run();
}
To load and run all plugins in \plugins\foo\, \plugins\bar\, (...) just use this code:
class Program
{
static void Main(string[] args)
{
var registration = new RegistrationBuilder();
registration.ForTypesDerivedFrom<IPlugin>().Export().Export<IPlugin>();
var directoryInfo = new DirectoryInfo("./plugins");
var directoryCatalogs = directoryInfo
.GetDirectories("*", SearchOption.AllDirectories)
.Select(dir => new DirectoryCatalog(dir.FullName, registration));
var aggregateCatalog = new AggregateCatalog(directoryCatalogs);
var container = new CompositionContainer(aggregateCatalog);
container
.GetExportedValues<IPlugin>()
.ForEach(plugin => Console.WriteLine(plugin.Run()));
Console.ReadLine();
}
}
As I said, I might be totally of the track but chances are also that someone looking for an alternative finds it useful :-)
How about using
Assembly.LoadFrom("..path)
You could add an EventHandler to the Appdomains AssemblyResolve event and then load your assemblies form your special private path.

CodeDom add reference to existing file

In visual studio, I can click on "Reference" > "Add reference" and browse to an existing .dll file from my computer. I can then use the referenced dll as follows:
dllNameSpace.dllClassName myReference = new dllNameSpace.dllClassName();
myReference.someVoid();
I know how to add a referenced assembly using codedom (will show this below), but the actual dll file is not being added to the project as it is when done through Visual Studio. Again, I need to be able to call some function in the dll file I'd like to reference.
What I'm doing now:
// Configure a CompilerParameters that links the system.dll and produces the specified executable file.
string[] referenceAssemblies = {
"System.dll",
"System.Drawing.dll",
"System.Windows.Forms.dll",
"System.Data.dll",
"System.Xml.dll",
"System.Management.dll",
Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + #"\myDllFile.dll"
};
CompilerParameters cp = new CompilerParameters(referenceAssemblies, exeFile, false);
I'm assuming that I will need to do something different in order to have CodeDom add the dll to the output executable file. What more needs to be done here?
Thanks for the help everyone!
Following code may help you in loading the assembly and invoke method.
Assembly asmbly = Assembly.LoadFile("assembly.test.dll");
var myclass = asmbly.GetType("MyClass"); // use FullName i.e. Namespace.Classname
var myobj = Activator.CreateInstance(myclass);
myclass.GetMethod("MyMethod").Invoke(myobj,new object[]{"param1","param2"});

Setting file version for a codeDOM file

I'm looking for ANY means of setting the file version for an exe file generated using codeDOM. Mine always comes out as 0.0.0.0. Programatically would obviously be preferred, but at this point anything would be better than nothing.
The version of the compiled assembly is controlled by the AssemblyFileVersion attribute. You just need to make sure this is included as part of your CodeDom tree when you compile.
You can set this by adding the attribute into the CodeCompileUnit AssemblyCustomAttributes member.
CodeCompileUnit unit = CreateMyUnit();
var attribute = new CodeAttributeDeclaration(
new CodeTypeReference(typeof(AssemblyFileVersionAttribute)));
attribute.Arguments.Add(
new CodeAttributeArgument(
new CodePrimitiveExpression("1.1.1.1")));
unit.AssemblyCustomAttributes.Add(attribute);

Categories

Resources