I've a directory with a large number of dlls. I need to find all those that reference a specific dll.
I'm thinking about the following solution :
Loop the assemblies and invoke each one with ildasm
Dump the manifest into a text file
Search the text files for the required assembly name.
Yet this solution feels immensely wrong to me. Is there a better way to achieve it?
You could write a small tool for that purpose, using Reflection to find the referenced assemblies:
string[] fileNames = ...; // get all the filenames
foreach (string fileName in fileNames) {
var assembly = System.Reflection.Assembly.ReflectionOnlyLoadFrom(fileName);
var referencedAssemblies = assembly.GetReferencedAssemblies();
foreach (var assemblyName in referencedAssemblies) {
// do your comparison
}
}
According to Microsoft documentationnn AppDomain.CurrentDomain.GetAssemblies() Gets the assemblies that have been loaded into the execution context of this application domain. About AppDomain.CurrentDomain.GetAssemblies()
It seems that you need to change strategy of loading the asseblies you need from using the appdomain to looking for dlls in your applications folder.
I found a discuss on similar problem here
Download AsmSpy.exe, it has the option to list all assemblies and all the references within the assemblies.
https://github.com/mikehadlow/AsmSpy
Download IlSpy.exe, and open the assembly whose references you want to see, it will list all referenced assemblies.
https://github.com/icsharpcode/ILSpy/releases
Related
Basically, I want to print a list on a page inside my MVC site that shows all the assemblies that are used by the application and there version information.
I don't want to just include those in the bin directory, I want to use a more accurate way.
So examples would be
I want to know which dll's within the bin directory are being used. For each of these, I need to see what their dependent assemblies are (with their version information).
I want to know which dll's are referenced from GAC, etc.
I want as much information on this as possible, so information like what version the assembly is expecting, and what the application is picking up would be useful.
Are there any standard approaches to this?
Thanks,
Martin
Consider using BuildManager.GetReferencedAssemblies which:
Returns a list of assembly references that all page compilations must reference.
Example usage:
var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();
Note also an important difference between this method and AppDomain.GetAssemblies(). BuildManager.GetReferencedAssemblies returns:
assemblies specified in the assemblies element of the Web.config file, assemblies built from custom code in the App_Code directory, and assemblies in other top-level folders.
while AppDomain.GetAssemblies() returns only assemblies currently loaded.
Try this:
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
today I'd like to know how do you configure your projects in C# WPF which references additional assemblies in a chain. By the "in a chain" I mean something like this:
we have application which refers to assembly Plugin
Plugin assembly refers Resources where resources used by Plugin are located, eg. images
main application does not refers to Resource in any way.
The following image illustrates what I've just said:
The problem is that Resources is not copied to the bin folder of the application, causing Plugin (Ctrl on the image) resources it requires finding failure.
Workaround
There are workarounds for it which are simply to include Resources to references of the main application or use a post-build step and manually copy required files in that step.
Conclusion
Concluding, I'd like to ask how do you deal with that problem. Are the any other solutions besides those I mentioned in workaround section? Am I missing something in the projects' configuration?
Make sure that the output directory in the Plugin project properties is same as the output directory of your application. Otherwise you have to copy files yourself as you do.
Second option would be using embedded resources.
If you load the plugin dynamically from a different folder than the EXE, you can also copy its dependencies to the same folder as the plugin and load those assemblies dynamically, as well. You then need to handle AssemblyResolve so that the already-loaded assemblies will be resolved instead of trying to find new assemblies:
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var domain = (AppDomain)sender;
var assemblies = domain.GetAssemblies();
return assemblies.FirstOrDefault(assembly => assembly.GetName().Name == args.Name.Split(',')[0]);
}
The code above does a version and strong-naming insensitive match; you can implement your own policy here if you want something stricter.
I'm trying to get a list of assemblies for NHibernate to scan. I'm using some sample code from a tutorial application:
IEnumerable<AssemblyName> enumerable = GetType().Assembly.GetReferencedAssemblies()
.Where(name => name.Name.StartsWith(assemblyPrefix));
foreach (var assemblyName in enumerable)
x.Assembly(assemblyName.Name);
So there are 3 projects: ProjectName, ProjectName.Services, and ProjectName.Data.
The problem is that the assembly that is configuring NHibernate doesn't actually use the Services project. I thought just adding a project reference would work, but it doesn't.
Is there any way to make my project reference Services, or should I just hardcode the assembly names in the configuration?
How about AppDomain.CurrentDomain.GetAssemblies() (docs)? That should return all the loaded assemblies, which would include ProjectName.Services even if the assembly you're calling this from doesn't use it, as long as it's used somewhere else (I think it additionally must already be loaded too).
Here's the setup:
A pure DotNET class library is loaded by an unmanaged desktop application. The Class Library acts as a plugin. This plugin loads little baby plugins of its own (all DotNET Class Libraries), and it does so by reading the dll into memory as a byte-stream, then
Assembly asm = Assembly.Load(COFF_Image);
The problem arises when those little baby plugins have references to other dlls. Since they are loaded via the memory rather than directly from the disk, the framework often cannot find these referenced assemblies and is thus incapable of loading them.
I can add an AssemblyResolver handler to my project and I can see these referenced assemblies drop past. I have a reasonably good idea about where to find these referenced assemblies on the disk, but how can I make sure that the Assmebly I load is the correct one?
In short, how do I reliably go from the System.ResolveEventArgs.Name field to a dll file path, presuming I have a list of all the folders where this dll could be hiding)?
When I have used this in the past we have just compared the file name with the part of the ResolveEventArgs.Name that has the name. If you want to be sure that you are loading the exact same version I suppose you could check if the names match, if they do then load the assembly and then check the assemblies full name against the ResolveEventArgs.Name.
something along these lines:
string name = GetAssemblyName (args); //gets just the name part of the assembly name
foreach (string searchDirectory in m_searchDirectories)
{
string assemblyPath = Path.Combine (executingAssemblyPath, searchDirectory);
assemblyPath = Path.Combine (assemblyPath, name + ".dll");
if (File.Exists (assemblyPath))
{
Assembly assembly = Assembly.LoadFrom (assemblyPath);
if (assembly.FullName == args.Name)
return assembly;
}
}
for completeness:
private string GetAssemblyName (ResolveEventArgs args)
{
String name;
if (args.Name.IndexOf (",") > -1)
{
name = args.Name.Substring (0, args.Name.IndexOf (","));
}
else
{
name = args.Name;
}
return name;
}
The Managed Extensibility Framework (MEF) sounds like something that'll solve all your problems. It can scan folders to locate DLLs, resolve dependencies for any depth and manages plug-in composition in general. Each part (or 'plug-in') just has to declare what it needs and what it provides, and MEF takes care of the wiring. If MEF succeeded in taming VS2010's extensibility beast, then it can handle anything.
I've never had luck with AssemblyResolver. I usually do one of these three:
Require plugins not have external references that are not in the GAC. If they bitch, tell them to ILMerge.
Require plugins to dump all their dlls into a known plugin directory. Load all assemblies in that directory into memory.
Require that plugin dependencies exist in a path that is probed by fusion. You can figure out where the binder is looking for assemblies turn on the fusion log (fuslogvw.exe--don't forget to reboot after turning on logging!).
I have a C# solution, which references a dll I created from a different C# solution.
It is easy enough to determine my solution's product version with Application.ProductVersion. However, what I really need is a way to determine the file version of the exe and the dll separately, within my program. I want to display the dll and exe's file versions in my About dialog. What would the code look like to do this?
The simplest way is if you know a type in the referenced assembly:
AssemblyName name = typeof(MyCompany.MyLibrary.SomeType).Assembly.GetName();
Assembly.GetName returns an AssemblyName which has a Version property indicating the version of the assembly.
Alternatively, you can get the assembly names of all assemblies referenced by the executing assembly (i.e., the .exe):
AssemblyName[] names = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
Perhaps the easiest solution is this:
var version = Assembly.GetAssembly(typeof(SomeType)).GetName().Version;
where SomeType is a type you know for sure that is defined in that particular assembly. You can then call .ToString() on this version object or look at its properties.
Of course, this will blow up in a huge fireball the moment you move your type into another assembly. If this is a possibility, you will need a more robust way to find the assembly object. Let me know if this is the case.
The AssemblyInfo class has all this information, so you just need to get a reference to the assembly in your code. For example:
Assembly.GetExecutingAssembly.GetName.Version.ToString()
You can get the other assemblies in the project in various ways, for example
var assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies();