I have a DLL I generate from a C# project. I then register it via regasm so that the library can be used inside several legacy VB scripts.
Recently I created a new project (C# console app) that will reuse certain modular aspects of the original library, and per good programming practice it made sense to add the library to the GAC for reuse by this and any future projects.
I've found that it plays nice at first, but after the server is rebooted, the VB scripts crash and burn, claiming they are unable to create an object of one of the types defined in the library.
The fix involves removing the library from the GAC and re-registering the library via regasm.
The libraries in the registry and GAC come from the same physical DLL file - same directory and everything.
I've confirmed the existence of registry entries for the library every step of the way, which says regasm did its job.
GAC entries only exist when the library is installed, and properly disappear when it is uninstalled. They only ever appear under GAC_MSIL, where, to my knowledge, they should be.
Any ideas why this is happening?
EDIT: I did not read the fine print, haha. On the regasm documentation I just saw this: "Creates a Codebase entry in the registry. The Codebase entry specifies the file path for an assembly that's not installed in the global assembly cache. Don't specify this option if you will subsequently install the assembly that you're registering into the global assembly cache. It is strongly recommended the assemblyFile argument that you specify with the /codebase option be a strong-named assembly." I was using that switch, so I will dig deeper. In the meantime any additional insights are greatly appreciated.
I would guess you didn't renew the GUIDs and/or distinguish the fully qualified type names of the new library and when you installed it with regasm, the old entries in the registry got overwritten. Registering the old library again has overwritten the new library's registry, but as you don't use it through COM that didn't affect it and now the scripts work again.
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.
I have a native dll (which is an activex control) that I need use with my .NET application without having to register the dll in the registry.
I have read several in depth posts about registration free activation, some of the better ones are
A lengthy one from Steve White and Leslie Muller
This one from samuel jack
And another from Mike Makarov
and from what I can see it is possible. However several hours and hundreds of tests later I just cant get it to work. I've done a bit of PInvoking and even less with ActiveX controls in .NET in my career, so would appreciate any input from anyone whom might have kicked goals on this before.
So far I'm following Steves advice, in terms of building an application that works and then trying to formulate the winning manifest file syntax via repeatedly running the regsvr32 command to add and remove the unmanaged dll's from the registry. Just a bog simple .Net console application with about 10 lines of code...
One part that I am confused about is the interop. The native dll's I have are also accompanied with managed runtime callable wrappers (RCW's). In my .NET application I add reference to these RCW's and then can consume the respective classes and functionality provided for by the unmanaged dll's. I'm not PInvoking via dllimport.
In creating the manifest files I'm unsure if I need to worry about these RCW's and how they work in a registration free scenario, or even if if they need to be in the compiled output?
I've also tried several tools such as (OLE/COM object viewer, Mt.exe from the windows sdk, and regsvr42 from codeproject). But the manifest structure and necessary GUID's all vary between tools and posts.
Current status is that I receive a InvalidCastException "Unable to cast COM object of type System.__ComObject to interface type MyFunkyDllLib.FunkyDllControl. This operation failed because the QueryInterface call on the COM component for the interface with IID '{some guid}' failed due to the following error: Library not registered.
Can anyone confirm the correct syntax for the application and dll manifest files ? Online posts even vary on the name with some using sxs in the name....
Update1:
Whilst Joe's answer below did not work it did give me some better insights into reg free COM. In the properties of the Interop dll (the one that that is added to the project reference from the list of installed COM components on the dev machine) I changed the Isolated Property to True. This has the effect of making VS dump a copy of the COM dll (not the interop, it is embeded in the exe) to the bin\debug folder. VS also then creates a myapplication.exe.manifest.
In this manifest file is supposedly sufficent information for reg free com. I found other posts indicating success with this method but in my case I still ended up with the same InvalidCastException.
Reading over Samuel Jacks post again, I tried his method of creating both a manifest for the exe and the COM dll using the clsid information from the VStudio output manifest when Isolated=true. (I also deleted the <file/> section created by VS from the exe.manifest). After unregistering the COM from the registry I now have success ! The application starts and does not error.
Why this approach works and not the Isolated=true I have no idea because it is beyond my knowledge of manifests and assemblies.
However we are still not at the wizards castle yet Toto.
Now I'm back at the same issue I posted on this SO thread. However in this scenario unit tests are not involved. Just a plain console application with 10 lines of code. Works fine when in normal registered COM mode, but not in reg free mode.
After many hours of trial and error I finally got a solution to how to successfully implement RegFree COM.
Here is a full explanation incase it helps someone else.
I create a new .NET class library in VS
Right click references and select the COM components of interest.
(Note: for the COM to be visible in the list they must be registered
on the development machine. This can be acheived by using the
Regsvr32.exe tool included with windows. Calling "regsvr32
mycomdll.dll" registers it in the windows registry)
Right click the COM reference, goto properties, and then set Isolated=True. This has the effect of causing VS to output a .manifest file supposedly containing all the registry details necessary for a consuming .exe to know what resources to load instead of querying the registry. However in my case it was incomplete. Calls to Interop methods would work, but events from the COM component would not. See step 5 for my solution)
Build the project. The .manifest should appear in the build output.
Open the manifest in notepad or similar. Within the <assembly /> tag I needed to add a <comInterfaceExternalProxyStub /> tag with appropriate IID, tlbid and proxyStubClsid32 GUID elements. Elements of the manifest are documented on msdn. In my case the proxy/stub was proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"/> which is the built in windows proxy. The iid and tlbid I originally discovered via Process Monitor whilst calling regsvr32. An easier and more reliable option I later discovered was to use a tool like SxS manifest maker as it added a second <comInterfaceExternalProxyStub /> that I originally did not have.
Create an exe project in VS and reference the previously built library.
Build the exe project.
Run regsvr32 /u mycomdll.dll. To remove all registry associations.
Run the exe. In my case calls to and events from the COM component in the class library worked perfectly.
Caveats: I dont know why VS does not include the <comInterfaceExternalProxyStub /> element automatically in the .manifest. At the time of writing the only way to automatically update the manifest was to add a post build Task in VS. In my case I copied the entire XML manifest into an XML in the class library project and then just overwrote the .manifest file in the build output.
Unit (integration) testing of the COM is inconsistent. Currently in my case calls to Interop methods work, but events do not. It has something to do with the fact that the Test Runner is not compiled with knowledge of the dependencies and therefore such are not present in the activation context.
You are probably missing a typelib declaration...but ignore that for now... Instead, do the following...
After playing with this on and off for a while, I decided that the easiest way to do it is using MSBuild and a GenerateApplicationManifest task. I've been using it with a unmanaged app, but I don't see why it would not work with a managed app. I say "app" ... because my app is managed but I have both COM libraries and .NET assemblies with ComVisible classes in them.
From your description it sounds like you are dealing with having COM and don't have to worry about consuming .NET assemblies from COM. You can google for MSBUILD and GenerateApplicationManifest to get an example MSBuild file.
So, I assume you will not need to populate the "Dependencies" attribute of the task. You will need to populate the "IsolatedComReferences" attribute with a list of your COM DLLs. They can be a simple semi-colon delimited list, but usually they are in "ItemGroup" declarations in the MSBuild project file. The COM DLLs need to be registered at the time you generate the manifest.
As for your RCW, there is nothing special you need to do. IMO, they don't need to be in the manifest. .NET has a way of finding them as long as they are in the same directory as your app/DLLs.
If you use MSBuild, you won't have to generate manifests for your COM DLLs... They probably already have manifests already... Usually, the wizards automatically generate manifests and embed them. The only manifest that will need the COM type information is the manifest you generate with MSBuild.
The whole point of the manifests used in this manner is to populate the manifest space with all the COM information that would be in the registry.
How can I use different dll's (other Version) with the same name in one directory?
For Example, LibA (ExternalLib.dll) has Version 1 and LibB (ExternalLib.dll) has Version 2.
I'm deploying all my programs to the same directory (this is our companys standard and I can't change this fact). The problem is if ProgramB which is using the LibB is deployed in the directory where ProgramA is using the LibA then ProgrammA would not longer work.
For my own Libs I use a Major-Version-Number (.01, .02) if there are big changes. But the Lib I'm using is an external Lib and each version of it requires different licensing-keys (which are handled by the programs itself).
I tried to rename the external libs from "ExternalLib.dll" to "ExternalLib.v1.dll" and "ExternalLib.v2.dll", but when I run my fresh compiled programm it throws an exception that says "ExternalLib.dll could not be found". The reference in my project is set to "ExternalLib.v1.dll" and compilation works fine.
Any ideas / suggestions to handle different assembly versions in the same directory?
Unfortunately, the filename of the DLL file has very little do do with how .Net is loading these types. The actual name is written into the meta data of the assembly as part of the compilation process. So at runtime, it will be probing for ExternalLib.dll regardless of what you renamed the file to. The usual way to fix this is to install to the GAC and use Strong Naming to reference the specific version.
Given you may not be able to do this, there are 4 things you could try:
Ask the vendor to produce version specific DLL's for you. They could compile such that the version name is part of the filename and included in the assembly manifest. This would be the simplest solution for you.
Handle the AssemblyResolve event and manually try and use Assembly.Load to point at the file you want such that you can specify specifically which dll to use. See http://support.microsoft.com/kb/837908 for more information, but effectively you'll be using Assembly.LoadFrom(specific_path) to choose the file where the code will load from.
If possible, you might also be able to use ildasm.exe to decompile the dll's to Intermediate Language (IL), then use ilasm.exe to recompile it to a new dll name. You would then reference this new DLL name in your project.
If the assembly is not signed, then you may be able to edit the manifest yourself; you can either use a compatible binary editor or possibly MT.exe.
I've been trying to get a registration-free .NET based COM DLL to work, but without success.
In Visual Studio 2008 I added a new C# class library.
I enabled the 'make assembly COM-visible' and 'register for COM interop' options.
I added a public interface and class with some functions.
I added a manifest dependency to my C++ client application: #pragma comment(linker,"/manifestdependency ...
But when I start my application I get 'the application has failed to start because the application configuration is incorrect'.
I've used Microsoft's mt tool to extract the manifest files of both the C++ client application and the C# COM DLL and the information in both is the same (the dependentAssembly in the C++ manifest file contains the same name and version as the assemblyIdentity in the COM manifest file).
I've also tried the approach described on http://msdn.microsoft.com/en-us/library/eew13bza.aspx but with similar results.
Similarly I tried to add a reference to my COM project in 'Framework and References' of my C++ client application. The information on that property page looked promising (it shows options like 'copy local', 'copy dependencies', etc and properties like the 'assemblyIdentity'), but Visual Studio neither copies the DLLs nor adds a dependency to the manifest file automatically.
Note that the 'registered variant' works fine.
Anyone have any ideas of what I'm doing wrong?
Update:
When I create a simple C++ DLL and embed a manifest with the same name and version of my .NET COM DLL (same assemblyIdentity) my application starts up fine. So the problem lies with the manifest file of my .NET COM DLL.
I can successfully extract the manifest from the DLL with mt -managedassemblyname:... and then embed the same manifest with mt -outputresource:..., but this also doesn't cause Windows to successfully resolve the dependency.
I found the steps needed to get registration-free .NET COM interop working myself :-)
Run: mt -managedassemblyname:"myDll.dll" -out:"myDll.manifest"
Clean manifest (see format at http://msdn.microsoft.com/en-us/library/eew13bza.aspx). Mainly I needed to remove all tags except for assemblyIdentity, clrClass and file (and specifically remove the runtime, mvid and dependency tags).
Run mt -outputresource:"myDll.dll" -manifest "myDll.manifest". Basically this adds the modified manifest as a resource to the DLL. Note that this is apparently not the same manifest (location)! If I reextract the manifest with the managedassemblyname option I still get the 'old' manifest. If I extract it with the inputresource option I get the new one.
I pretty much found this all thanks to Windows Vista. Unlike my Windows XP it contains a tool called sxstrace that gives rather detailed information about the problems with side-by-side execution.
When I did this, I started with a very simple, basic component to get the COM stuff sorted. Also I used a script client in the initial development.
I did not use Visual Studio, but instead a text editor for the .NET code. I inserted the GUIDs for the assembly and for the Interfaces, and marked the interfaces for AutoDispatch.
using System;
using Interop=System.Runtime.InteropServices;
namespace Whatever
{
[Interop.Guid("xxxxxxxx-9120-4283-b972-changethis05")]
[Interop.ComVisible(true)]
[Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)]
public partial class MyClass :
...
}
I made sure my class had a default (no-arguments) constructor.
I ran regasm /codebase by hand, from the command line, specifying the .NET assembly.
I hand-coded the javascript to instantiate the object.
When things were confusing, I checked the ProgId with OleView.exe.
Once you have the very basic stuff working, add complexity gradually, until you get the working solution.
You can also use the approach from the other direction; from the client. .NET Assemblies like System.Random are marked for COM interop when you install .NET, so you can use them to verify that your approach in C++ is correct. Instantiating a System.Random ProgId is something like the "hello, World" of C++-to-.NET-via-COM. If that succeeds, then you know the basic approach in C++ is sound.