How to get list of all .NET assemblies programmatically? - c#

I have an application to write dynamic assembly in runtime, so I need to a list of all assemblies in my system like Visual Studio Reference Manager:
My question is: How to fetch a list of all .NET Assemblies by self .NET languages and without searching a folder files?
Note:
I know I can find any assemblies from:
C:\Windows\assembly\GAC\...
or
C:\Windows\Microsoft.NET\Framework
but I not sure to find that assemblies in all system by this way!
Because I do not have access to these folders on all computers. So my app only through .NET code can fetch the names of these assemblies. And other problem is that the path to this folder on all the computers are not fixed and may vary.

You should really have a look on GAC Manager project on Codeplex :
https://gacmanager.codeplex.com/
It will be really helpful and nice to use for your purpose. On the project page you'll also find a working sample (not tried with .Net 4.6 by me anyway, hope it works well also for this one)

You can execute gacutil.exe/i command directly from your code to get list of all GAC assemblies. You can see a sample code here: https://social.msdn.microsoft.com/Forums/vstudio/en-US/d9283b0f-94b7-4fe2-9196-92f81c6e7ba0/obtaining-list-of-assemblies-present-in-gac?forum=clr

On my PC Visual Studio simply reads the contents of this directory to display this info:
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5
As a test, I deleted Accessibility.dll
YMMV

Related

External DLL write in C and use in C# [duplicate]

I have a dll library with unmanaged C++ API code I need to use in my .NET 4.0 application. But every method I try to load my dll I get an error:
Unable to load DLL 'MyOwn.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
I have read and tried several solutions I have found on the internet. Nothing works..
I have tried using following methods:
[DllImport("MyOwn.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs((UnmanagedType.I4))]
public static extern Int32 MyProIni(string DBname, string DBuser_pass,
string WorkDirectory, ref StringBuilder ErrorMessage);
When I tried following this article and when I run this example (from the downloaded code) it runs without a problem (the dll used is in the bin/debug folder)
I have copied my dll (along with all the files the it depends on into my bin folder).
I also tried this approach but got the same error:
[DllImportAttribute(MyOwnLibDllPath, EntryPoint="TMproIni")]
[return: MarshalAs(UnmanagedType.I4)]
public static extern int MyproIni(string DBname, string DBuser_pass,
string WorkDirectory, ref StringBuilder ErrorMessage);
Any suggestions?
From what I remember on Windows the search order for a dll is:
Current Directory
System folder, C:\windows\system32 or c:\windows\SysWOW64 (for 32-bit process on 64-bit box).
Reading from the Path environment variable
In addition I'd check the dependencies of the DLL, the dependency walker provided with Visual Studio can help you out here, it can also be downloaded for free: http://www.dependencywalker.com
You can use the dumpbin tool to find out the required DLL dependencies:
dumpbin /DEPENDENTS my.dll
This will tell you which DLLs your DLL needs to load. Particularly look out for MSVCR*.dll. I have seen your error code occur when the correct Visual C++ Redistributable is not installed.
You can get the "Visual C++ Redistributable Packages for Visual Studio 2013" from the Microsoft website. It installs c:\windows\system32\MSVCR120.dll
In the file name, 120 = 12.0 = Visual Studio 2013.
Be careful that you have the right Visual Studio version (10.0 = VS 10, 11 = VS 2012, 12.0 = VS 2013...) right architecture (x64 or x86) for your DLL's target platform, and also you need to be careful around debug builds. The debug build of a DLL depends on MSVCR120d.dll which is a debug version of the library, which is installed with Visual Studio but not by the Redistributable Package.
The DLL has to be in the bin folder.
In Visual Studio, I add the dll to my project NOT in References, but "Add existing file". Then set the "Copy to Output Directory" Property for the dll to "Copy if newer".
This is a 'kludge' but you could at least use it to sanity-test:
Try hard-coding the path to the DLL in your code
[DllImport(#"C:\\mycompany\\MyDLL.dll")]
Having said that; in my case running dumpbin /DEPENDENTS as suggested by #anthony-hayward, and copying over 32-bit versions of the DLLs listed there into my working directory solved this problem for me.
The message is just a bit misleading, becuase it isn't "my" dll that can't be loaded - it's the dependencies
Try to enter the full-path of the dll.
If it doesn't work, try to copy the dll into the system32 folder.
"Unable to load DLL 'xxx.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)" means the file CAN be found BUT it's not able to load it. Try to copy the DLL file to the root folder of your application, some DLL libraries need to be available in the root folder of the application in order for it to work. Or check if there are any other depending DLL files required by it.
"Cannot find DLL 'xxx.dll': ..." means the file CANNOT be found. Try to check the path. For example, [DllImport(#"\Libraries\Folder\xxx.dll")]
Ensure that all dependencies of your own dll are present near the dll, or in System32.
Turn on the fusion logging, see this question for lots of advice on how to do that. Debugging mixed-mode apps loading problems can be a right royal pain. The fusion logging can be a big help.
Make sure you set the Build Platform Target to x86 or x64 so that it is compatible with your DLL - which might be compiled for a 32 bit platform.
There is one very funny thing (and has a technical relevance) which might waste your hours so thought of sharing it here -
I created a console application project ConsoleApplication1 and a class library project ClassLibrary1.
All the code which was making the p/invoke was present in ClassLibrary1.dll. So before debugging the application from visual studio I simply copied the C++ unmanaged assembly (myUnmanagedFunctions.dll) into the \bin\debug\ directory of ClassLibrary1 project so that it can be loaded at run-time by the CLR.
I kept getting the
Unable to load DLL
error for hours. Later on I realized that all such unmanaged assemblies which are to be loaded need to be copied into the \bin\debug directory of the start-up project ConsoleApplication1 which is usually a win form, console or web application.
So please be cautious the Current Directory in the accepted answer actually means Current Directory of main executable from where you application process is starting. Looks like an obvious thing but might not be so at times.
Lesson Learnt - Always place the unamanaged dlls in the same directory as the start-up executable to ensure that it can be found.
I had the same problem when I deployed my application to test PC. The problem was development PC had msvcp110d.dll and msvcr110d.dll but not the test PC.
I added "Visual Studio C++ 11.0 DebugCRT (x86)" merge module in InstalledSheild and it worked. Hope this will be helpful for someone else.
In my case one unmanaged dll was depending on another which was missing. In that case the error will point to the existing dll instead of the missing one which can be really confusing.
That is exactly what had happen in my case. Hope this helps someone else.
If the DLL and the .NET projects are in the same solution and you want to compile and run both every time, you can right click the properties of the .NET project, Build events, then add something like the following to Post-build event command line:
copy $(SolutionDir)Debug\MyOwn.dll .
It's basically a DOS line, and you can tweak based on where your DLL is being built to.
I think your unmanaged library needs a manifest.
Here is how to add it to your binary. and here is why.
In summary, several Redistributable library versions can be installed in your box but only one of them should satisfy your App, and it might not be the default, so you need to tell the system the version your library needs, that's why the manifest.
Setup: 32-bit Windows 7
Context: Installed a PCI-GPIB driver that I was unable to communicate through due to the aforementioned issue.
Short Answer: Reinstall the driver.
Long Answer:
I also used Dependency Walker, which identified several missing dependency modules. Immediately, I thought that it must have been a botched driver installation. I didn't want to check and restore each missing file.
The fact that I was unable to find the uninstaller under Programs and Features of the Control Panel is another indicator of bad installation. I had to manually delete a couple of *.dll in \system32 and registry keys to allow for driver re-installation.
Issue fixed.
The unexpected part was that not all dependency modules were resolved. Nevertheless, the *.dll of interest can now be referenced.
I have come across the same problem, In my case I had two 32 bit pcs.
One with .NET4.5 installed and other one was fresh PC.
my 32-bit cpp dll(Release mode build) was working fine with .NET installed PC but Not with fresh PC where I got the below error
Unable to load DLL 'PrinterSettings.dll': The specified module could not be
found. (Exception from HRESULT: 0x8007007E)
finally,
I just built my project in Debug mode configuration and this time my
cpp dll was working fine.
Also faced the same problem when using unmanaged c/c++ dll file in c# environment.
1.Checked the compatibility of dll with 32bit or 64bit CPU.
2.Checked the correct paths of DLL .bin folder, system32/sysWOW64 , or given path.
3.Checked if PDB(Programme Database) files are missing.This video gives you ans best
undestand about pdb files.
When running 32-bit C/C++ binary code in 64bit system, could arise this because of platform incompatibility. You can change it from Build>Configuration manager.
I faced the same problem when import C++ Dll in .Net Framework +4, I unchecked Project->Properties->Build->Prefer 32-bit and it solved for me.
It has nothing to do with dependencies if you checked all dependencies and you know you got them all, it has nothing to do with the file being in the wrong directory either or incorrect ARGUMENTS passed to dll, the DLL Fails to load using LoadLibrary itself.. you could check the address returned from LoadLibrary is always 0x0000000 (not loaded).
I couldn't figure this error out either it worked fine on Windows 7, but on Windows 10 it doesn't work. I fixed the problem though it had nothing to do with missing dependencies or Runtime redistributable packs.
The problem was I had to pack the DLL with upx and it started working again.
Something with the file being unpacked and compiled on old Windows XP operating system created a bad PE Header or Bad file format or something, but packing it with UPX did the trick works fine now and the DLL got 3x smaller haha.
I got this error for one C++ project in our solution, and only on our buildmaster's machine. The rest of us could build it with no problem.
In our case it was because that particular project had <WindowsTargetPlatformVersion> in the .vcxproj file set to "10.0" vs. "10.0.18362.0" as in all our other C++ projects.
Not specifying the entire SDK version number seems to have allowed MSBuild to choose the newest(?) SDK and associated build tools.
Our buildmaster likely had the remnants of a newer SDK on his machine, and MSBuild was trying to use it (and thus RC.exe was not found).
In any case, bringing up the project's property page and changing Configuration Properties > General > Windows SDK Version to "10.0.18362.0" (or whichever specific version of the SDK you have installed) for all of the project's configurations/platforms did the trick.

Combine .NET external dlls to a single executable file

This is a simple question. I just can't run my program if the Newtonsoft.Json.dll is not in the program folder. Why this? I've tried adding the reference, added the file to the project root, added to the resources folder, but nothing worked. How to run the program without the Newtonsoft.Json.dll in the program folder? I'm developing in a Windows Form Application.
UPDATE
Problem solved, thanks to spender for introducing me the ILMerge, a really really nice NuGet package that can combine third party dlls to a single executable binary file. For who wants to make a standalone application, just use ILMerge. Rapid, easy and extremely useful. See ya!
Usually, if your program uses a DLL, then you'll need that DLL in the app folder (or in the user path, or the GAC).
The conventional method of distributing multiple files is with an installer. You can write one using either WiX or the VS Installer Projects extension. Now all your output files get installed in one go along with all the other goodness that comes with an installed program. I have a strong preference for this method.
However, there are alternatives:
Download the source and copy the source into your main project, then it will be compiled into your main assembly (make sure you check that this is permitted by the license).
Use ILMerge to combine all your assemblies into a single binary.
If you don't want to reference dll in your program, you can install it to GAC on client machine but I don't understand which the context you want
If you just need some JSON serialization. Can you switch out your functionality with the JavascriptSerializer class which is installed with .Net?
http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer(v=vs.90).aspx

Visual Studio solutions - correct location for utility EXEs needed by your solution

Is there a proper place in a Visual Studio solution for .exes required by your solution. For example I'm working on a tool now that needs VHDCreate.exe, ISOCreate.exe, OSClone.exe and other exes. What is the right way to include them in a solution? I've inherited a solution where they are just stuck inside a folder inside the business layer project of the solution.
I'm using Visual Studio 2010.
I would suggest having a nicely organized tools folder at the level of the solution. Then you can use a solution folder to organize it separate from the rest of the projects.
This is with a native .dll but the concept is the same.
Add existing item to solution and pick any folder where binaries exist:
Select add as link from whatever folder outside solution you keep the binaries
In the solution explorer set it as Copy if newer.
The .exe or .dll will be copied to the build output folder if needed.
When the original .exe gets updated the build will pull the newer one in the output folder.
You might want to read Mike Roberts series, How to Set Up a .Net Development Tree. The way Visual Studio does it by default is essentially broken, as far as I'm concerned.
How to Set Up a .Net Development Tree, Introduction
How to Set Up a .Net Development Tree, Part 1
How to Set Up a .Net Development Tree, Part 2
How to Set Up a .Net Development Tree, Part 3
How to Set Up a .Net Development Tree, Part 4
How to Set Up a .Net Development Tree, Part 5
How to Set Up a .Net Development Tree, Part 6
How to Set Up a .Net Development Tree, Part 7
Single *.pdf: How to Set Up a .Net Development Tree
Fundamentally, your directory structure should look like this:
Meta/Development RootUsually mapped to root of source control system.
SolutionOne directory, contain your entire solution. Should be named to match the solution.
Solution.slnThe solution file itself.
nant.buildThe nAnt build file for the solution.
libThe lib directory contains 3rd party assemblies/dlls that are referenced by the different projects in your solution. It is under source control. Project references should point here.
toolsThe tools directory contains all 3rd party tools required to build your solution. It, too, is under source control. The tools directory should contain the versions of nAnt, nUnit etc. used by your project — and your build scripts should reference these, rather than the version(s) installed on a developer's machine.
binThe bin directory contains the output of the build process for the solution. Each projects must be configured to point here.
debugdebug build
releaserelease build
objIn the ideal world, each project's obj would be pointed here as well as this has no place in the source tree. Sadly, Visual Studio doesn't offer an official way to do that (though, I'm told, VS can be hacked to do so if you're resourceful enough).
srcThe src directory is the root directory for the actual source code of your solution.
project1The directory for project1.
project.csproj`The project file.
*.cs, etc. files. The source files.
...
project-n
How to structure individual projects is, I think, an entirely separate topic, but there should be, WRT to both the solution and the individual projects a correspondence between namespace and file system hierarchy. If a particular project requires a 3rd party assembly that is not to be available to other projects in the solution, an argument could be made for each such projects' directory to its own lib directory, but that scatters 3rd party assemblies across the source tree and so is not recommended.

Find location of standard .NET assemblies?

For a little C# compiler, I need to find the paths of the standard .NET assemblies like System.dll, System.Xml.dll and pretty much all the assmeblies listed under the ".NET" tab in the "Add Reference" window in Visual Studio (2010).
I would use the absolute paths but I have a feeling that this can break in exceptional cases.
These are all stored in the GAC at %WINDIR%\assembly, which you can view in Windows Explorer.
The actual dlls can be found in subfolders of the GAC, GAC_32, and GAC_MSIL folders, seemingly dependent on their version. On my machine I have three additional NativeImages folders that also appear to contain GAC'd dlls.
Windows Explorer won't allow you to browse these folders directly (as far as I can tell), but you can get there via the command prompt.
The full path for a dll in the GAC is
%WINDIR%\assembly\GACFOLDER\FILENAME\VERSION__PUBLICKEYTOKEN\FILENAME.dll
e.g. On my machine different versions of System.Xml.dll can be found in C:\WINDOWS\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c561934e089
C:\WINDOWS\assembly\GAC\System.Xml\1.0.5000.0__b77a5c561934e089
C:\WINDOWS\assembly\NativeImages1_v1.1.4322\System.Xml\1.0.5000.0__b77a5c561934e089_2775eea1
C:\WINDOWS\assembly\NativeImages1_v1.1.4322\System.Xml\1.0.5000.0__b77a5c561934e089_4c5fbb92
When compiling, you can use the reference assemblies under %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\.NETFramework
Also see the registry keys under (HKEY_LOCAL_MACHINE|HKEY_CURRENT_USER)\SOFTWARE\Microsoft\.NETFramework and (HKEY_LOCAL_MACHINE|HKEY_CURRENT_USER)\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders, as documented by KB306149.
The GAC is intended more for run-time use.
Most are in the GAC, which is where I believe you are instructed to look with your own compiler. The document that helped with compilers, etc., was found under the .NET Framework in older versions, under the tools developer folder.
I would not be totally adverse to "hardcoding" the folder, per se, but you will be locked to a specific version. I am not suggesting this is the right way, but the location of .NET is not likely to change and most likely your compiler is stuck in a specific version. If you go this route ... To be safe on various machines, you should use %WINDIR% to determine where windows is installed (try cd %WINDIR% in a command prompt if you have never used this and want to see what the variable does). Academic exercise over.
One thing to note is some of what you are attempting may be served better by examining the "compiler as a service" direction MS is heading in vNext (?). This idea/feature is already present in Mono (open source .NET).

How to get assembly version of a project in a visual studio 2008 deployment project

I have a deployment project in visual studio 2008 that installs several C# projects. Among other things, I'd like it to write projects assembly version to registry.
Is there a way to automatically find out whats the projects assembly version (written in AssemblyInfo.cs) and write that as value of a registry property?
If not, is there any way to do this better than by hand? It is important that these values are correct because they are used by our updating software.
Thank you.
EDIT: I'm not sure I was completely clear in my question. I don't want to get this number and store it to a string. I want to write it to registry with Deployment Projects Registry Editor (not sure if that's the official name, you can get to it by right clicking the deployment project in solution explorer and navigating to View->Registry)
This should work:
Assembly.GetExecutingAssembly().GetName().Version.ToString();
Make sure this is called from each Projects main assembly.
The GetName method returns an AssemblyName object that has other useful info as well.
Edit:
You could make the assemblies self-registering, that requires them to be run once to update the registry.
If that is not acceptable can write a plugin for setup (and/or run a separate program). And from within that code you need to get the filename of the assembly being installed.

Categories