I have an ASP .NET 4.0 project which depends on two native dlls, lets call them Native.Lib.dll and Native.Lib64.dll (32 and 64 bit respectively). Our project is built as AnyCPU and we dynamically load one of the two native libs based on the value of IntPtr.Size.
The native libraries are installed same directory as the rest of the binaries. Whenever I run the project, I get:
BadImageFormatExceptionCould not load file or assembly 'Native.Lib64'
or one of its dependencies. An attempt was made to load a program with
an incorrect format.
And when I switch IIS to 64 bit, it has the same complaint about 'Native.Lib'. From the research I have done, it looks like ASP.net loads all dlls in the directory on startup and blows up because of a "bitness" mismatch.
I have found that I can remove these binaries from the initial load in the Web.config file using <remove assembly="Native.Lib"/> and <remove assembly="Native.Lib64"/>, but I am worried that when it comes time to load these assemblies, they won't be able to load.
Furthermore, there are two other native assemblies already in the directory that ASP.net doesn't seem to have a problem with. (the developer that already solved this problem is no longer with the company). There are no <remove> tags in the config file for them, but ASP doesn't seem to mind.
Is there a way I can get ASP.net to ignore these files without removing them? If not, will the dlls be available when I call Assembly.LoadFile()?
Related
I am currently working on a project which requires the use of a custom dll for authentication.
This dll is registered (so they told me) in the GAC of both the Production and Test environments.
The company policies state that you "shouldn't include the dll reference in your application's web.config file", that is, you shouldn't have something like :
<add assembly="" ....="" mydll=""> etc.
in your web.config, at least for this dll I am talking about. They say, since it's registered in the GAC, the application will load it anyway.
The problem is , if you don't add the assemby reference in your web .config , the application is not going to find it , no matter what they say.
Since I am sure the dll is actually registered in the GAC, my question is :
shouldn't the application be able to load the dll anyway , no matter if you add the reference in the web.config or not ?
I was convinced that, adding the reference to the project, the dll 's GAC location would be stored in the application's assembly so that the application itself would be able to find the assembly in the GAC , no matter what the working system is , given that the dll is actually registered in the working system's GAC .
But I must be wrong.
What is the real way it works ?
I tried deleting the <add assembly ...> entry from the web.config : I have a runtime error everytime I reference a method in the dll , in my test environment ; same thing happens in the Production environment;
shouldn't the application be able to load the dll anyway , no matter if you add the reference in the web.config or not ?
By the logic applications would load every assembly in the GAC when they start up, could you imagine how slow that would be? No, that's not how it works.
When you reference a DLL locally in your project, all you are doing is adding it into the manifest which tells the application to load it as part of your application. When the CLR loads, it would first of all check if there is an equivalent version of your DLL in the GAC, if one exists it will load that version, if not it would attempt to load the local version.
See How the Runtime Locates Assemblies
I created a C# project on my computer that uses ODP.net, I imported the reference of Oracle.DataAccess. On my PC, I try to do a connection to the Database and it works normally, however, if I copy the .exe file of my application in another computer, it does not work and I receive the following error:
System.IO.FileNotFoundException: Could not load file or assembly
'Oracle.DataAccess, Version=4.112.3.0, Culture=neutral,
PublicKeyToken=89b483f429c47342' or one of its dependencies. The
system cannot find the file specified. File name: 'Oracle.DataAccess,
Version=4.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342'
Why doesn't C# encapsulate all the files needed in the .exe? What can I do to make this program work regardless of the executing computer?
As of request by Vito, here is my comment as an answer:
I suggest to not use the "classic" ODP.NET which has dependencies on additional installed ODP components on the system, but instead use the purely managed version of ODP.NET.
For the managed ODP.NET you have a single assembly (i.e. a DLL) that you can ship with your application (e.g. in the "bin" folder if it is an ASP.NET application) and you're done.
Just to make it complete, the connection string in my cases looks something like:
<add
name="ora"
connectionString="Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=MyServer)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=XE))); User Id=MyUser; Password=MyPassword"
providerName="system.data.oracleclient" />
The managed version was really a huge improvement in terms of ease-of-use in my projects.
you must have installed version of the Oracle Database on each machine where you intend to install your application.
Another option is to go to Oracle and download just drivers.
Download from Oracle, then you need to include them with your project, reference this dll.
Please see the answer to a similar question I had. Mainly this problem is about oracle.dataaccess.dll, it's build platform (32 or 64) and presence of some of it's dependencies (like OraOps11w.dll). These things should be checked to see if are present and configured correctly. It would get big in deployment! Of-course if you are calling the library at machine level (not app level) from different applications, you should check if it's registered in GAC too.
Edit: In it's simplest form:
1 - You need to have these dlls in your app directory: OraOps11w.dll, oci.dll, orannzsbb11.dll and oraociei11.dll.
2 - You have to add a reference to Oracle.DataAccess.dll.
Where can one get these?
1 - From the installation directory of you Oracle Client (not Server), if you already had installed the oracle client (including ODP.NET).
2 - If you have installed ODT.NET.
3 - By getting ODP.NET (preferably the zip archive, not the install package).
There are TONS of possible causes to your problem here. I would first start by copying the entire folder than contains the .EXE file, and not just the .EXE file itself. There are things in this folder that your .EXE needs in order to run. Also, I would check the dependencies on the computer that is not working with the program Dependency Walker. Things can go wrong if you develop on a 32-bit and try to run on a 64-bit. Things can go wrong if you develop on Windows and try running on MAC. There is a lot that can change from one computer to the next, and your code must be ready for that. Dependency walker can tell you if you aren't connecting to certain dependancies (mostly .DLL's) correctly. If you go into the release folder that contains your EXE, if there exists any .DLL files in that same directory, these .DLL's are likely needed on any computer that will try and run this program.
I wrote a dll c++/cli library which uses my other c# dll library. C++/cli library works fine when I've got c# dll in the same folder as application which calls it. This library will be finally loaded to many applications and a C# dll must not be copied into directory with application. It has to be in the same folder as c++/cli library, but in that cases I've got System.IO.FileNotFoundException.
My suggestion is to load c# library manually or to change path where f.ex. firefox is looking for dependencies, but I tried with LoadLibrary() and Assembly::LoadFrom() methods to force loading from right directory. Of course I added directory path with dll to system PATH.
I work on VS2010.
You don't change the default directory where an application will look for dlls.
At design time put your dll in some well know location, the one you are going to deploy to. Add a reference to it, make sure it's set to Don't copy ever, otherwise it will end up in the bin folder. You have to do this otherwise it won't compile.
When you deploy, you'll need one package to deploy common dlls, and one for each application. Careful you don't create your own version of dll hell, if appA needs an older or new version of the common dll, compared to AppB
Add an AppDomain.AssemblyResolve event to main (for windows app). At run time the event handler will get fired when you reference a type in your dll, and the assembly has not yet been loaded.
In there you load it from the well known location. That usually in config, or in a relative path.
E.g.
AllMyApps
CommonDLLS
MyFirstApp
So the path you load the required common dll from would be "..\CommonDlls\MyCommondll.dll".
NB you will want to secure the dlls in some way, otherwise a bad guy might be able to inject their version of one in to your app, which would be bad...
You can use this mechanism to get the dll from a remote server or a database blob as well.
The simplest case is only a few lines of code, just look the event up. Took me about 15 minutes to get this going in a similar scenario.
Not on this machine though, otherwise I'd have pasted in the code.
I have a COM-visible dll "COMInterface.dll" which is deployed into an existing application's folder. I have created a test harness that has verified the functionality of this dll.
However, when I try to use classic asp to call one of this dll's methods I get a message like the following:
MyCompany.MyProject.COMInterface (0x80070002)
Could not load file or assembly 'MyCompany.Framework, Version=2.6.4202.14897, >Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
My "COMInterface.dll" references a number of other dlls such as my company's standard framework, logging classes etc. "Framework" is one of these such dlls.
Where will the asp page be looking for these dlls? I am guessing that my harness worked because it was being run from the program folder whereas the asp page is within an IIS web site.
Do I need to use GAC registration here? I'm hoping not as there would be quite a few dlls I would need to deploy there and I am hoping to extend the application without having to impact the core installation on users' machines.
Thanks in advance of your questions and suggestions.
[EDIT]
I should point out that the object can be created fine. It's the location of the referenced dlls that are causing the problem.
When you use Regasm to register the dll you need to use the /Codebase switch to ensure the dll can be found.
As a general answer, you can use Fusion Log Viewer to determine what paths have been searched by the assembly binder.
See http://msdn.microsoft.com/en-us/library/e74a18c4.aspx for information on this tool.
Fusion Log Viewer will list all the paths probed by the binder. If you put your assembly into any of these paths it will be found. Whether any of these paths will be suitable for your scenario I'm not so sure.
I have a weird situation with some code that I inherited at work. Their application is a multi-project solution, with several of the solutions being (code) pieces of the MS Enterprise Library (not sure which version).
They also have an existing C++ (unmanaged) application which has a bunch of DLLs. One of these DLLs is built in a separate solution, both in 64-bit and 32-bit flavours.
The main application has a reference to this DLL, and calls a couple of static functions (I can see intellisense, even). I can compile and build the main application EXEs, but when I run it, I get an exception that this DLL from the unmanaged code (lets call it CPlusPlusCode.dll cannot be found:
FileNotFound Exception was unhandled: Could not load file or assembly 'CPlusPlusCode.dll' or one of its dependencies. The specified module could not be found.
I'm quite stumped, because I can compile the code, see intellisense for the imported classes, and dig into the DLL in the object browser. I even made sure there's a copy in the \bin\Debug folder (although I don't see why that would make a difference). This is for a Windows Forms application.
Also, if it matters, I had some build issues related to x86 vs. x64 for different projects; I think (hope?) that this is not related to that, but I solved that by using the Configuration Manager to build everything as x64.
Check the GAC, and if necessary you might need to add it or register the DLL there.
I had this problem with a project, it all works ok from Visual Studio and most of my times running the project locally on my machine. But because of the unmanaged code I needed specifically allow the project to be executed with correct permission levels.
So have a look in the manifest file, that enough permissions etc exist.