There are some authentication changes recently in our company and we are supposed to change the authentication systems in all the applications. We have a dll (Auth.dll) that has this logic about the authenticaion. All our applications has these Auth.dll file and uses the same logic for authentication.
Our strategy for this is to just modify the dll to use new authentication logic. The method signatures remains same, since those are the methods we call from other places in all our applications.
We have an archive application (built on .Net framework 2.0) in our company which a few users still use.The problem for these archive applications is that we dont have the source code. So i am just trying to create a new dll and replace it on the production server on the location where old dll was hosted. Everything else stays the same.
I created the new dll using framework 2.0. I have unit tested it and works fine.
The issue i am getting is -
Could not load file or assembly 'Auth, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ae1958e6e8b32d9c' or one of its dependencies. The system cannot find the file specified.
I checked the public key token on the new Auth.dll and it looks ok. The version also looks ok.
The Auth dll has the references to only 4 .Net framework 2.0 assemblies.
Any idea what may be wrong?
Thanks
You could easily get the source code for the dll by using something like http://ilspy.net/, this would then allow you to get the source code and recompile. I've always has a hard time tracking down these types of issues, but again if you use ILSPY you should be able to see all of the DLL's that the Auth.dll is referencing.
As an absolute last resort you could use some of the tools from sysinternals to see what is being accessed on the hard drive when this is being loaded to see if the reference dll simply isn't there. Hope this helps.
Did you register auth.dll in the gac, or put it in the archive applications bin folder?
Also if the archive application was referrencing the old auth.dll, then the signature of the new one will need to match the old one exactly, and by that I mean it's full qualified type name.
E.g.
Auth, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ae1958e6e8b32d9c
Needs to be the same now as it was before.
Or you'll have to do as punkcoder suggested and rebuild the source with ILSpy or use ILDASM and change the reference and ILASM to put it back together.
Do you search in C:\Windows\assembly and find the assembly ?
Case no, you have to install or get the same version of your component.
Related
I have some projects that rely on external .Net assemblies to operate. These are installed externally from my program so I do not have direct control over what version is being used. Furthermore, updates are expected to be installed as a matter of course.
For example, in one case I am accessing a hardware device that provides a .Net interface to control it. When the user initially installs the device, they install the driver that is included. This driver when I wrote the program may have been 3.0.4.0. The latest version might be 3.1.8.0.
My program fails to load the assembly when this happens complaining that the manifest definition is incorrect. A specific exception message is show below.
Another example is a labeling program. They provide a .Net interface to allow my program to print labels through their system. Installing an updated version of the program is fatal.
Here is the specific exception message:
Could not load file or assembly 'SDK.NET.Interface, Version=17.1.0.0,
Culture=neutral, PublicKeyToken=865eaf3445b2ea56' or one of its
dependencies. The located assembly's manifest definition does not match
the assembly reference.
If I install this version of the application on my computer, then reference the updated version of the assembly and compile, I’m good to go . . . for now.
But, it’s only a matter of time before I will have the issue again.
I’ve tried setting the Specific Version property of the referenced assemblies to False but that didn’t affect the problem.
What is the proper way to address the issue?
You are able to "Plug and Play" as long as method signatures don't change.
If those change, then you'll need to fix your base code.
Look at Microsoft's documentation on Redirecting Assembly Versions:
http://msdn.microsoft.com/en-us/library/7wd6ex19%28VS.71%29.aspx
Another option is If these libraries are somehow controlled by you or your company, you might have some wiggle room with reflection by loading them up by their base type/interface and using common methods... but you'll need to have access to the base types.
This is also a duplicate question:
Upgrade a reference dll in a C# project without recompiling the project
Upgrading dependent DLL without recompiling the whole application
I have a C# COM-Interop assembly which I am calling from a Visual Basic 6 application. This assembly makes HTTP requests to send and retrieve JSON.
The assembly works fine when being testing with a C# test client.
However, when using it from with the VB6 app, the following error is returned:
"Could not load file or assembly 'Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified."
The Newtonsoft.Json.dll is located within the same folder as the COM-Interop DLL (TLB).
Does the Newtonsoft.Json.dll need to be explicitly loaded? Or maybe placed in the GAC?
Hans provided a great explanation for why this happens. Let me offer a workaround for making this work without having to register the Json DLL in the GAC or copying it to the VB6 EXE directory.
In your COM-visible C# library, we can tell the .NET runtime environment to search for the Json DLL in the directory of the C# library instead of the "usual" paths. We do that by attaching our own handler to the AssemblyResolve event:
AppDomain.CurrentDomain.AssemblyResolve += (sender, e) =>
{
// We only want this workaround for one particular DLL
if (e.Name != "Newtonsoft.Json")
return null;
var myLibraryFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var path = Path.Combine(myLibraryFolder, "Newtonsoft.Json.dll");
return Assembly.LoadFrom(path);
};
Notes about this workaround:
This code only works if it is executed in your C# library before doing anything that might cause the jitter to load the JSON library. For example, neither your library nor any other .NET library in your VB6 process must call any method referencing types from the JSON library before this code is executed.
You modify the the behaviour of the whole process, not just your library. If your VB6 process uses another library using JSON, your "redirect" affects the other library as well.
This is a standard DLL Hell problem, it is caused by using the /codepage option for Regasm.exe. Or, more commonly, the Project > Properties > Build tab > "Register for COM interop" checkbox. Both do the same thing, they write the path to the DLL into the registry. It is a very good option to use when you are busy developing and testing the project, it avoids having to re-register the DLL into the GAC every single time you make a change.
But what it does not do is help the CLR find any dependencies. The normal probing rules remain in effect, it looks for an appname.exe.config file in the directory where the EXE is stored. And first looks in the GAC, next in the EXE path for dependencies. Configuration remains under control of the usual victim of DLL Hell, whomever has to maintain the EXE. Frequently the end-user. So, explicitly, it does not look in the directory where your [ComVisible] DLL is stored.
It is the mild kind of DLL Hell, just a plain file-not-found mishap. Much milder than the nasty kind, finding a file with the right name but the wrong version. In general a strong problem with Newtonsoft.Json.dll, there are about 35 versions in the wild. Having so many versions and it being such a popular library also begets the other kind of nastiness, the program using another COM server that also uses the DLL. But almost inevitably a different version. Tends to happen long after you declared your project finished. One of them is going to lose, 50-50 odds that it is you. 100% odds for the end-user.
Yes, the GAC solves this problem. Each library gets the version they ask for. Ideally Newtonsoft would solve this problem for you with an installer that deploys the DLL into the GAC. But it is not the kind of commitment that open source library writers ever want to provide. They want (and need) to make it your problem. Microsoft does this, but they also have Windows Update to ensure that critical bug and security fixes get deployed. And have a large number of people working on making sure that any new revisions are always backwards compatible with the original release so the version number doesn't have to change.
Do note that you can take advantage of Microsoft's commitment. You can also use the DataContractJsonSerializer and JavascriptSerializer classes to get this job done. Part of the framework, they rarely get it wrong.
Meanwhile, do keep mind that is just a file-not-found problem. You don't have to use the GAC on your dev machine, and it is better if you don't, it is just as easy to copy the file into the right place to keep the CLR happy. Which is the same directory as your VB6 test program. And, extra quirk with VB6, into C:\Program Files (x86)\Visual Studio\VB6 if you want to use the VB6 debugger. Do use the GAC when you deploy.
I'm looking at incorporating the new Google Apps Script Execution API into an existing C# plugin i have already working. I am following the .NET quickstart guide provided as a console application (which i have gotten working without problem).
When porting the code from that into my plugin it will also fail at runtime at the first instance of:
UserCredential credential;
which I slimmed down the code so far to just that line which fails giving:
"Could not load file or assembly 'Google.Apis.Auth, Version=1.9.2.27817, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab' or one of its dependencies. The system cannot find the file specified."
The file is properly referenced (having installed via nuget).
C# is not my normal field and perhaps i'm missing something in the subtlety of it working in a Console App.
What gives?
There was a time when console apps defaulted to using the client profile rather than the full .Net framework. Check the properties of the project on the Application tab and make sure the target framework doesn't end with Client profile. If that doesn't work try using the fusion log viewer, which you'll find conviently located at C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin, or any number of other places. Run it as an admin and it'll tell you what it can't load (which may or may not be Google.Apis.Auth) and where it looked for the file at.
This has been a little bit of a red herring. Not very well documented is the fact for the app i am building against, Autodesk Navisworks,
plugin dependency libraries have to be duplicated in a separate directory altogether from the plugins directory.
Easily fixed for the build environment, but will need a little more thought for when creating a distributable.
I have a Visual Studio 2010 C# project which creates an .exe and this project is using some 3rd party class library.
My project is located in: /MyFramWork/tests/test1
3rd party library is located at: /MyFrameWork/bin/utils/
I am adding the reference to the library by using References->Add Reference->Browse. I can see that in the project file all is fine:
....\bin\utils\log4net.dll
False
I would like to reference the 3rd party library without using the option "Copy Local". However if I don't use the option, the library is not found and I get an exception.
My question is: Is there a way to specify that the 3rd party library should be found at ....\bin\utils. It seems that when the .exe gets build the information from the .csproj gets lost.
By default, .NET apps look for their dependencies in only two places: the EXE directory, and the GAC (Global Assembly Cache).
You have three choices:
You can make sure the dependency gets copied into the same directory as your EXE (this is what Copy Local does). This is the best choice most of the time, which is why it's the default when you reference an assembly that's not already in the GAC.
You can install your dependency into the GAC using gacutil. This might be a good choice if your dependency isn't going to change, is going to be in a different location on every development machine (i.e. if relative paths won't work well), and if you want to use it from many different projects. But it's a major pain if the dependency is still under active development and changing frequently. You'll also need to make sure to put the DLL into the GAC on every computer you deploy your app to.
You can customize the dependency-loading behavior so it looks in other places, as Hans noted in his comment. This is an advanced option and comes with a whole new set of headaches.
Normally, you would just use Copy Local; it's a very sensible default. You should need a fairly compelling reason to do anything different.
Use the <probing> element to specify where the CLR should search for your assemblies. The only restriction is that the assemblies must be located in subdirectories of your application's base directory.
For example, if your application base directory is C:\MyFramework, then you could have your assemblies in C:\MyFramework\bin.
Have a look at this article to learn how the CLR searches for assemblies.
If you need to load assemblies from custom locations, you could try the Assembly.LoadFile Method.
The following links may be useful:
C# - Correct Way to Load Assembly, Find Class and Call Run() Method
http://www.csharp-examples.net/reflection-examples/
It's me Potzon. I am still investigating this incredibly silly problem.
I have been hoping for some elegant solution. I am about to build fairly large framework with lots of assemblies which would be placed inside /Framework/bin/. However I wanted to have some directory structure inside the the directory, for example /bin/utils, /bin/test, /bin/devices/ and so on.
One possible solution that I have found is to define environmental variable DEVPATH (see here http://msdn.microsoft.com/en-us/library/cskzh7h6.aspx) but it turns out that .net4 is not using this variable when an assembly is run independently (outside the visual studio), or at least this is the case for me - I can't make it work.
It seems that the solution to put all the assemblies inside the /bin directory without using sub-directories is the best. I think I will give up and just do it this way.
Is it necessary to register a compiled DLL (written in C# .NET) on a target machine.
The target machine will have .NET installed, is it enough to simply drop the DLL onto the target machine?
I think you're confusing things a little. Registering a dll has never been needed in order to use it.
Using a dll requires only to load it (given a known location or if the library is in the system path) and get the address of the function you wanted to use.
Registering the dll was used when distributing COM or ActiveX objects which need to add certain entries to the windows registry. In order to use a COM service (for example) you need to reference a GUID — that is, a unique identifier — which allows you to get a handle to the dll that implements the service (or provide access to it). Sometimes you can make reference to a fully-qualified name and get the same results.
In order for all that to work the dll needed to be registered. This "registration" process just creates several entries in the registry, but mainly these two: one associating a GUID with the location of the dll (so that you can reference it through the GUID without knowing where is it exactly located) and a second one associating the full name with the GUID. But again, this is just for COM or ActiveX objects.
When you develop an application in .NET, the libraries referenced on your project are automatically loaded when they're needed without you having to worry about locating or loading them. In order to to that, the framework checks two locations for the referenced libraries.
The first location is the application path.
The second location is the GAC.
The GAC (Global Assembly Cache) allows you to effectively register a dll to be used throughout the system and works as an evolution of the old registering mechanism.
So basically you just need to put the dll in the same folder of the application.
You need to "drop" it into a directory where the application needing it will find it.
If there are multiple applications, or you want to "drop" the file somewhere other than the application directory, you generally need to either adjust the PATH variable, or register the assembly in the Global Assembly Cache (GAC).
It is usually enough to drop the dll into the folder of your app on the target machine.
If the dll must be available to other applications then you may want to consider the GAC.
If you wish to access the assembly via com+. An example would be using a type defined in a .NET assembly from a non .NET application, such as a VB6 winforms app.
If you plan on accessing the assembly from another .NET application, you don't have to do anything. If your assembly has a strong name, it probably is a good idea to drop it in the GAC. Otherwise, just drop it in the directory of the application that will be referencing it.
One of the great selling points of .NET for the Windows platform when it came onto the scene is that by default, .NET assembly DLLs don't have to be registered and can be consumed privately by an application by merely putting them in the same folder as the EXE file. That was a great stride forward because it enabled developers to avoid the fray of DLL/COM hell.
Shared DLL/COM modules proved to be one of the greatest design mistakes of Windows as it lead to instability of applications that users installed. Installing a new app could well screw up an app that had been working just fine - because the new app introduced newer versions of shared DLL/COM modules. (It proved in practice to be too much of a burden for developers to properly manage fine-grained version dependencies.)
It's one thing to manage versions of modules with a build repository system like Maven. Maven works extremely well doing what it does.
It's an entirely different matter, though, to deal with that problem in an end-user runtime environment spread across a population of millions of users.
The .NET GAC is by no means a sufficient solution to this age-old Windows problem.
Privately consumed DLL assemblies continue to be infinitely preferable. It's a no-brainer way to go as diskspace is extremely cheap these days (~$100 can by a terabyte drive at Fry's these days). There is nothing to be gained with sharing assemblies with other products - and yet company reputation to loose when things go south for the poor user.
Actually there is NO need to register a dll in .NET on the target machine.
If you reference a .dll in your application, click on the referenced .dll under references in your project, look at the properties and set Isolated to TRUE.
This will now automatically include this .dll in your project and your application will use the copy of the .dll included in your project without any need to register it on the target system.
To see a working Example of this look here:
http://code.msdn.microsoft.com/SEHE
The .dll in question will need to be registered on the system where you build your application for this to work properly. However once you build your project, there will not be any need to register the .dll in question on any system you deploy your application or program.
An additional benefit of using this method, is that even if in the future, another .dll is registered with the same name on the target system in question, your project will continue to use the .dll you deployed with. This is very handy where a .dll has many versions and you wish to maintain some stability, like using the one you tested with, yet all other applications will use the registered .dll unless they use the isolated = true method as well.
The example above is one of those cases, there are many versions of Skype4COM which is a Skype API .dll and can change often.
This method allows the above example to use the API .dll that the project was tested with, each time a user installs a new version of Skype, it is possible that a modified version of this .dll is installed.
Also, there are some Skype clients that do not install this .dll, the business version of the Skype client for example, is smaller, and does not include this .dll, so in this case, the project does not fail on that .dll missing and not being registered because it is included in the project as isolated = true.
An application can use a .NET dll by simply having it present in the same folder with the application.
However if you want other third-party applications to find the DLL and use it they would also have to include it in their distribution. This may not be desirable.
An alternative is to have the DLL registered in the GAC (Global Assembly Cache).