Get Assembly Names in Current Application Domain - c#

I want to get Assemblies Friendly Names in Current Application Domain and hence I wrote something like this :
static void Main(string[] args)
{
foreach (System.Reflection.Assembly item in AppDomain.CurrentDomain.GetAssemblies())
{
Console.WriteLine(item.FullName);
}
}
But the problem is this is the output what I got rather than what I desired to see :
mscorlib, Version=2.0.0.0,
Culture=neutral,
PublicKeyToken=b77a5c561934e0
ApplicationDomains, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null
Actually I was expecting those names :
alt text http://www.pixelshack.us/images/xjfkrjgwqiag9s6o76x6.png
Can someone tell me if there is something I mistook.
Thanks in advance.
Or the names I was expecting weren't assemblies ?

You won't always get the pretty namespace names when you use reflection, you get the real names of the assemblies.
You also won't get all referenced libraries, only the ones that CURRENTLY loaded. If you add "XmlDocument foo = new XmlDocument()" above your code, System.XML will show up.
static void Main(string[] args)
{
XmlDocument foo = new XmlDocument();
foreach (System.Reflection.Assembly item in AppDomain.CurrentDomain.GetAssemblies())
{
Console.WriteLine(item.FullName);
}
}
Output:
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
ConsoleApplication2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

It's impossible to get list of all referenced assemblies during runtime. Even if you reference it in your visual studio project, if you don't use them, C# compiler will ignore them and therefore they won't make it into your output file (exe/dll) at all.
And for the rest of your assemblies, they won't get loaded until they are actually used.
AppDomain.CurrentDomain.GetAssemblies() gives you array of all loaded assemblies and this list could be very different from what you see in visual studio project.

foreach(var assem in AppDomain.CurrentDomain.GetAssemblies())
{
Console.WriteLine(assem.GetName().Name);
}
Assembly.GetName() returns an AssemblyName object which has a Name property. That's what you're looking for.

Either use Assemly.GetName().Name or use reflection to find the AssemblyTitleAttribute and use that value.

Related

Dnspy compilation error without editing the code

The 'ConnectionState' exists in both 'System.Data.Common, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and 'System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
bool flag2 = this.sqlite_conn.State != ConnectionState.Open;
if (flag2)
{
this.sqlite_conn.Close();
this.sqlite_conn.Open();
}
Getting above error in this line of code while using dnspy.
Error code is CS0433 from main.cs
Check your project references and using statements and remove any unused ones.
Try to explicitly put the proper namespace in front of your enum, like:
System.Data.ConnectionState.Open;

Could not load file or assembly but they are loaded

I have a project going on witch uses a DLL from an ERP system.
The DLL is used to get information from the ERP, like invoices and such.
The error i am getting is:
Inner Exception 1: FileNotFoundException: Could not load file or
assembly 'SnelStartGatewayInterface, Version=12.48.37.0,
Culture=neutral, PublicKeyToken=null' or one of its dependencies. The
system cannot find the file specified.
But in the same window I used 'watch 1' to see the current using assembly's with the method:
AppDomain.CurrentDomain.GetAssemblies()
It returns a couple of assembly's.
This is the one loaded in and exactly the same as seen in the error:
+ [36] {SnelStartGatewayInterface, Version=12.48.37.0, Culture=neutral, PublicKeyToken=null} System.Reflection.Assembly
{System.Reflection.RuntimeAssembly}
Why would it return me the error?
Ps. I have tried the exact same method and dll in a windows forms test app and it was running fine.
Like Pawl Lukasik mentioned in the comments, you should look at the dependencies.
To do this, use:
private List<string> ListReferencedAssemblies()
{
List<string> refList = new List<string>();
var assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
foreach (var assembly in assemblies)
{
refList.Add(assembly.Name);
}
return refList;
}
to see all referenced assemblies.
Or with LINQ:
private List<string> ListReferencedAssemblies()
{
return Assembly.GetExecutingAssembly().GetReferencedAssemblies().Select(x => x.FullName).ToList();
}

Instantiating a class produces ReflectionTypeLoadException at Assembly.GetTypes()

I discovered that after my application generates Telerik report
var result = new ReportProcessor().RenderReport("PDF", new InstanceReportSource { ReportDocument = new MyTelerikReport(data) }, null);
var stream = new MemoryStream(result.DocumentBytes);
return CreateHttpFileResponse("MyReport.pdf", stream, "application/pdf");
I am not able to get all types within CurrentDomain
var typesWithAttribute = (from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetTypes() //error appears here
//some filtering logic
select t).ToList();
I am getting error
System.Reflection.ReflectionTypeLoadException: Unable to load one or
more of the requested types. Retrieve the LoaderExceptions property
for more information.
LoaderExceptions:
System.IO.FileNotFoundException: Could not load file or assembly
'DocumentFormat.OpenXml, Version=2.0.5022.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The
system cannot find the file specified. File name:
'DocumentFormat.OpenXml, Version=2.0.5022.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35'
After some investigation I found that assembly that fails to load: Telerik.Reporting.OpenXmlRendering, Version=8.0.14.311, Culture=neutral, PublicKeyToken=a9d7983dfcc261be and that assembly doesn't exists in AppDomain.CurrentDomain.GetAssemblies() before I generate report (I assume that assembly loaded dynamically by Telerik.Reporting, Version=8.0.14.311, Culture=neutral, PublicKeyToken=a9d7983dfcc261be).
I could filter out that assembly as I don't need any types from that but I am a bit worried about fact of having assemblies in domain that cannot be loaded - seems a bit wrong to me.
Could someone explain what there happens? Is it my issue or that is fault of 3rd party library that doesn't load all required assemblies?
The issue is not the assembly but the Type coming from a dependent assembly that has not been loaded.
If the GetTypes method is called on an assembly and a type in that assembly is dependent on a type in an assembly that has not been loaded (for example, if it derives from a type in the second assembly), a ReflectionTypeLoadException is thrown.
http://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettypes(v=vs.110).aspx

Find out dependencies of all DLLs?

I have a collection of DLLs(say 20). How do I find out all the DLLs on which one specific DLL (say DLL A) is depending upon?
If you mean programmatically, use Assembly.GetReferencedAssemblies.
You can use that recursively to find all the assemblies you need. (So you find the dependencies of X, then the dependencies of the dependencies, etc.)
Since the question is tagged "C#", I would assume you are talking about managed dlls (assemblies). In that case, dependencywalker is not useful. If you want to do that with a program, good ones are dotPeek by JetBrians and Reflector by RedGate. Or you can even use the object inspector in Visual Studio.
However, it can be a long process and cumbersome too. I would write a short C# program/F# script that uses Assembly.GetReferencedAssemblies, as Jon mentioned.
If instead you want to examine native DLLs dependencies with a program (C# code), you have to walk the examine the PE file (the MS dll and exe file format) and its IAT (import address table). Not easy, but not impossible...
I would start here on MSDN and here to understand PE sections, and use a managed library to read it (there are many, including some from the Mono project (I'm thinking of Cecil, it should work with native binaries too); in the past I have used this one from the good John Gough.
All answer credit goes to previous authors for the usage of Assembly.GetReferencedAssemblies. This is just a write-and-forget C# console app that works solely for .NET assemblies. return 0 on assemblies you were able to check, and when successful, outputs them to STDOUT. Everything else will return 1 and print some kind of error output. You can grab the gist here.
using System;
using System.Reflection;
using System.IO;
namespace DotNetInspectorGadget
{
class DotNetInspectorGadget
{
static int Main(string[] args)
{
if(args.GetLength(0) < 1)
{
Console.WriteLine("Add a single parameter that is your" +
" path to the file you want inspected.");
return 1;
}
try {
var assemblies = Assembly.LoadFile(#args[0]).GetReferencedAssemblies();
if (assemblies.GetLength(0) > 0)
{
foreach (var assembly in assemblies)
{
Console.WriteLine(assembly);
}
return 0;
}
}
catch(Exception e) {
Console.WriteLine("An exception occurred: {0}", e.Message);
return 1;
} finally{}
return 1;
}
}
}
Usage:
call %cd%\dotnet_inspector_gadget.exe C:\Windows\Microsoft.NET\assembly\GAC_64\Microsoft.ConfigCI.Commands\v4.0_10.0.0.0__31bf3856ad364e35\Microsoft.ConfigCI.Commands.dll
Output:
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
You can use dependency walker http://www.dependencywalker.com to figure this out. Take note on the difference between x32 and x64 though.
Dependency Walker is a free utility that scans any 32-bit or 64-bit
Windows module (exe, dll, ocx, sys, etc.) and builds a hierarchical
tree diagram of all dependent modules.
For .NET assemblies, a terrific tool to view the assemblies an assembly is dependent on is AsmSpy.
If you want the DLL's (the files) then, Assembly.GetReferencedAssemblies will also return the .Net Framework assemblies.
Here is a simple code snippet that will get the dll's it can find in the current directory (and also include some other related files):
private readonly string[] _extensions = { ".dll", ".exe", ".pdb", ".dll.config", ".exe.config" };
private string[] GetDependentFiles(Assembly assembly)
{
AssemblyName[] asm = assembly.GetReferencedAssemblies();
List<string> paths = new List<string>(asm.Length);
for (int t = asm.Length - 1; t >= 0; t--)
{
for (int e = _extensions.Length - 1; e >= 0; e--)
{
string path = Path.GetFullPath(asm[t].Name + _extensions[e]);
if (File.Exists(path)) paths.Add(path);
}
}
return paths.ToArray();
}
You can call it like so: MessageBox.Show(string.Join("\r\n", GetDependentFiles(Assembly.GetEntryAssembly())));

Create a application like Visual studio object Browser

I want to develop an application like Visual studio Object Browser, i.e. user will enter something like System.Text namespace or system classes. After button click, we have to find out all classes, functions, properties etc. inside the "System.Text".
I tried the following, but that failed.
Assembly SampleAssembly;
SampleAssembly = Assembly.Load("System.Text");
Type[] Types = SampleAssembly.GetTypes();
// Display all the types contained in the specified assembly.
StringBuilder str = new StringBuilder();
foreach (Type oType in Types)
{
str.Append(oType.Name.ToString() + "</br>");
}
divAsseblyData.InnerHtml = str.ToString();
'System.Text' is a namespace not an assembly so i assume you want to load the assembly 'System'.
To use Assembly.Load() with a string parameter you need to pass the fully qualified name of the assembly.
To obtain the fully qualified name you can do something like this:
Assembly SampleAssembly;
SampleAssembly = Assembly.Load(typeof(System.Activator).Assembly.FullName);
// get the type of some random object in the assembly (Activator) and then
// call .Assembly.FullName which returns the fully qualified name of the assembly
Or you can press Win + R, type "Assembly" and enter, then right click -> proprieties on the assembly which you need and set manually the proprieties in code in the format:
"mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
SampleAssembly = Assembly.Load("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");

Categories

Resources