Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assembly being copied local when it shouldn't be

Here's my sample scenario. I have a Console application and a class library dll (call it libraryA). The LibraryA dll has a reference to Oracle.DataAccess.dll version 4.112.2.0. The Oracle DLL is in the GAC. The reference to the Oracle DLL in LibraryA is "Copy Local = false." So far so good. If you build the libraryA dll, then Oracle.DataAccess.dll does not show up in its output directory. OK. Now I reference the libraryA dll in my console app. The reference to libraryA dll is "copy local = true". Now, when I build the console application, the Oracle.DataAcess.dll does show up in the output directory for the console application. However, it appears that the ONLY DLL that acts this way is the Oracle dll. Here is the complete code from LibraryA

public void Foo() {            
   Oracle.DataAccess.Client.OracleConnection c = new Oracle.DataAccess.Client.OracleConnection();
   WebMatrix.WebData.OAuthAccountData x = new WebMatrix.WebData.OAuthAccountData("asd", "asd");            
   DevExpress.Web.ASPxCallback.ASPxCallback cvv = new DevExpress.Web.ASPxCallback.ASPxCallback();
}

WebMatrix and DevExpress are also in the GAC just like the Oracle DLL. However, neither of those DLLs are output to the output directory, only the Oracle dll. Why? What's happening here?

For that matter, you can create another class library, call it libraryB, DON'T put libraryB in the GAC, reference LibraryB from LibraryA and set copy local = false. Even when you do that, libraryB is not copied to the output directory of the console app. Of course, in this case, the program blows up because it can't find library B, but at least Visual Studio is respecting the copy local flag = false. What is different about this stupid Oracle DLL?

Oh, one other thing that's funny. If, in my console application, I explicitly add a reference to the Oracle.DataAccess.dll, and say copy local = false, then it doesn't show up in the output directory. It seems kind of hilarious that to not have a DLL show up in the output directory, I have to actually reference it :)

Edit:

Another clue. Oracle, in order to torture developers, do not have one DLL built for AnyCPU. They have an x86 and and an x64 version. In my case, I am referencing an x86 version and building for AnyCPU. However, if I build for x86 (to match the oracle dll), then the Oracle DLL is not copied to the output directory. when building in AnyCPU, MSBUILD says: "warning MSB3270: There was a mismatch between the processor architecture of the project being built "MSIL" and the processor architecture of the reference "Oracle.DataAccess, Version=4.112.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86", "x86". This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project." So, it almost looks like Msbuild is ultimately deciding that, ok, you have a mismatch, so let me go ahead and copy this dll to your output directory, thereby guaranteeing that your application will blow up. :)

like image 868
aquinas Avatar asked Feb 17 '13 17:02

aquinas


1 Answers

By not referencing it, you are letting it use implicit rules. Well, the implicit default here is "copy it local", because most dlls are not in the GAC. The IDE has the crazy notion of defaulting to "make it work", which means "assume it isn't going to be in the GAC".

If you want to use explicit rules, then yes: you need to tell it what you want. And the way you do that is by adding a reference, and then by setting the options you want.

like image 94
Marc Gravell Avatar answered Sep 28 '22 05:09

Marc Gravell