Here's the problem I have. I need to inherit from two classes in C#, which can't be done. So I've set my class to inherit from one class and implement an interface for the other. I did the interface first, and all worked well. Then issues started arising when inheriting from the class. At first, it would compile, but on implementing the class I would get:
The assembly 'XXXXXXX\bin\x86\Debug\Resource.dll' does not have a strong name.
Easy enough, I signed my projects. But now I get an issue when building with my references that were working before:
The type 'WPResourceEvtLib.IWPResourceEvt' is defined in an assembly that is not
referenced. You must add a reference to assembly 'Interop.WPResourceEvtLib,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=567474567455'
I have WPResourceEvtLib.tlb which has been registered, and a Interop.WPResourceEvtLib.dll, whoch shouldn't be required. And if I add the Interop.WPResourceEvtLib.dll to the references I get:
Cannot embed interop type 'WPResourceEvtLib.tagWPResErrorType' found in both assembly
'XXXXXXX\Interop.WPResourceEvtLib.dll' and
'XXXXXXX\obj\x86\Debug\Interop.WPResourceEvtLib.dll'. Consider setting the 'Embed
Interop Types' property to false.
This is .net3.5, so there is no 'Embed Interop Types' option, but I did find those options in the cproj files - they did nothing though. I'm either so very close, or I'm completely wrong in my implementation. What could it be?
Sorry for a mostly non-answer, but the amount of supporting questions got large, and that way it will be more readable.
First, what is the nature/kind of XXXXXXX\bin\x86\Debug\Resource.dll? If .Net, then why TLB file? Is it COM and native? Or COM/OCX? Or just a normal .Net assembly with some ComVisible types? What is WPResourceEvtLib? Is it the "name" of that Resource.dll?
"Back then", when your assemblies were not signed, everything worked fine? What exactly have you changed? Which project got signed and what are the relations/references between the projects? Are all those projects inside the same solution and are they built simultaneously and they do reference-by-sibling-project, or maybe you build some parts separately and only reference-by-GAC, or, worse, reference-by-path-to-DLL? It might be just that you forgot to refresh/rebuild some references and they still link to the old unsigned versions?
Finally, why do you think that your implementation of inheritance and interface caused anything? Did you do some low-level stuff like manually writing IL, COM metadata, etc? The only thing the inheritance/implementation problem could actually cause is to force you to reference an assembly X to get the definition of the base class and assembly Y for the definition of interface, nothing more. It has nothing to do with signing or being unsigned. It all just about references to correct assemblies.
Let's start guessing. So, back to the references. First error message tells you that, your project references assembly X that was using another assembly Y and your project tries to use a class/type that belongs to Y but without explicitely referencing the Y (ie. it peeked it from X assembly). It cannot be done. When T.dll uses X.dll that uses Y.dll, whenever X.dll returns a Y-type to the client from T.dll, the T.dll must reference the Y.dll or else it will not be able to use that Y-object. Now note the change: when unsigned, everything worked. So your project "unsigned T" had used "unsigned X" which used "unsigned Y". If that compiled, it means that T reffed both X and Y. After signing you got error that "signed T" does not reference "signed Y". How did does SEE the new signed Y? If it REFERENCED it, then the error would not show up. Hence, it means that "signed T" has indeed referenced "signed X" which indeed is referencing "signed Y". BUT: as the error claims that signed T does not reference signed Y, it may mean that the signed T project is still referencing the old unsigned Y. Now if you actually add the reference to the signed Y, you will get a type clash: same types will be visible in old unsigned Y and new signed Y. Hey, everything seems to fit.
It might have happened if you added a reference from T to a Y.dll by path and forgot to rebuild that Y.dll at that path. That can be really silly: i.e. in T you have clicked "add reference" and "browse" and pointed to "Release\Y.dll", and then forgot to rebuild it and only have rebuild the T/X/Y in DEBUG modes. That way, one old unsigned version would linger in the cache directories and the T would still try to use it, while the referenced X would already be relinked to new signed Y.
have you tried the simpliest possible thing: clean everything, delete all bin/obj folders, remove all references, add the references back and rebuild?
Related
I recently took over a project and have little VS COM experience so please forgive me if I am not asking the right questions..
I have a C++ project which generate a COM dll, lets name it abc.dll.
I have another C# project which references the COM dll, however under the references, it is pointing to Interop.abc.dll. I deleted all abc.dll within the directory and interrop.abc.dll to see how the project would react, upon starting the project, interop.abc.dll is automatically generated. This boggles my mind because I dont know how interop.abc.dll is generated.
So here are my questions:
How does the C# project reference the interop.abc.dll initially if this is generated?
How is the interop.abc.dll generated if there is no abc.dll to begin with (I havnt built it)
I played around with the project and then interop.abc.dll stopped generating and was causing errors, why is it?
COM declarations are stored in a type library. Which is very similar to .NET metadata, COM was the grand-father of .NET, metadata that tells a compiler what types are stored in an assembly. Type libraries however use a fairly awkward binary format, it is very different from .NET metadata. Different enough to make the conversion from a type library to .NET metadata non-trivial. Some constructs have no conversion at all, some are troublesome enough that you ought to know about it.
So the .NET team decided that the conversion should be a separate step, one that could display warnings, or errors, when the type library content doesn't match .NET metadata closely enough. That conversion tool is Tlbimp.exe, the type library import tool. They did add this feature to the Project + Add Reference dialog. As long as the conversion doesn't generate any warnings that this works just fine. It very often does.
So the job of Tlbimp.exe, and the IDE in the case of Add Reference, is to mechanically translate the type library content to .NET metadata content. By convention, a type library named "Foo" is converted to "Interop.Foo.dll". It doesn't have to be, just the default name. You'll end up with a .NET assembly that doesn't contain any code, just metadata. .NET types that any .NET compiler can directly consume and otherwise match the type library declarations. The [ComImport] attribute is a very important one that tells the CLR that the metadata is actually for COM types.
So this all explains bullet 1. Bullet 2 is a no-go, you really do need the type library. It is very often embedded as a resource in the unmanaged DLL, Tlbimp.exe knows how to find it. Nobody can see the errors in 3 so of course it is unguessable what the problem might be. Just keep in mind that the conversion is not always without trouble, the point of making the conversion step explicit.
Can anyone tell me in what order assembly resolving takes place when I have the following situation?
In my bin I have my exe and 2 dll's:
Assemblies A (version 1), B and C merged into X (so 4 assemblies into 1)
Assemblies A (version 2)
all references I made did not include the UserSpecificVersion parameter.
Now, during a call in my exe, which A is being used?
Also, during a call in assembly B, which A is being used?
And what if it is the other way around (so first from B and then my exe)
Is there any documentation on this?
all references I made did not include the UserSpecificVersion parameter.
I'll assume you actually meant the "Specific Version" setting for a reference assembly and that you set it to False. This has no effect at runtime, only at compile time. When you added the assembly, it recorded the [AssemblyVersion] of the reference assembly. If you then, later, recompile your program but it finds a reference assembly with a different version then it won't complain but use the new one as-is. This is in general risky and you'd only do this when you try to limp along after you lost the original reference assembly and have no clue to what degree the new one changed. Always leave this setting at the default of True, only use False if you dug yourself a deep hole you cannot get out of.
At runtime it will always insist on finding the assembly with the correct display name and [AssemblyVersion] that was recorded from the reference assembly. You'd in general have trouble when you have two assemblies with the same name and namespaces, you tend to need extern alias to dig yourself out of that hole. Using ILMerge could indeed be a workaround, that changes the display name of the assembly. That however still leaves you with conflicting namespace+type names, it isn't clear how you sailed around that obstacle.
So the typical outcome is that the EXE will try to find A2, using the renamed assembly display name, and B will try to find A1. I can't nail it down with 100% fidelity from the provided info. If you have a non-typical case then use Fuslogvw.exe to get a trace of the assembly bindings. Be sure to select the "Log all binds" option.
I am working on an assignment that specified "Do not use any external libraries". So I created a c# application, and the first thing I did was remove all the dll's references by default... including "System.dll".
However, I can still add this to my code:
using System;
using System.IO;
I was just curious as to how come I do not need to have System.dll as a reference in my project to do this. Thanks!
mscorlib.dll includes items in both those namespaces.
You need to right-click your project > Properties > Build > Advanced... and check "Do not reference mscorlib.dll" to remove this reference.
Different assemblies can contribute to the same namespace.
Even if you don't reference System.dll, you are still referencing (implicitly) mscorlib.dll which contributes many types to the System namespace.
These references are probably defined in your Web.config or the Machine.config file so they're included by default.
These are the default libraries.I think your question is that "Dont use third party dlls"
Another thing to consider is, if you're compiling directly through the command line, a default set of switches, including default library references, is parsed by the compiler through the default response file (csc.rsp), located in the same directory as the compiler. The fact that you are able to import namespaces from the Base Class Library without explicitly referencing them at compile time is due to the fact that their containing assemblies are included in your program by default. To change this behavior at the command line, you can use the /nostdlib switch to force it not to include mscorlib.dll, or you can use /noconfig to have it ignore the entire default response file altogether. Also, I'm not too sure what you mean by system.dll, because the namespaces you mentioned are contained within mscorlib.dll. Also, I think by "external library", your instructor must have meant any 3rd party assemblies that would assist you in solving the problem. Anything that comes included with the .NET SDK would be more of a framework library. Unless your teacher is really harsh and wants you to reinvent the wheel :P
The full error is as follows:
The type
'System.Windows.Forms.Control' is
defined in an assembly that is not
referenced. You must add a reference
to assembly 'System.Windows.Forms,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.
and it points at the very first statement (an Debug.Assert line) in the very first class in a library project that doesn't need System.Windows.Forms (or so I thought). I know how to solve it: add the mentioned reference. But how do I find out what library is causing this error, or better, what part of the code triggers using the WinForms library?
Normally, you can add libraries that reference others, but you only need to add references to these others when they're actually used.
EDIT: Alternative solution
This or similar problems can also be resolved using the Binding Log Viewer Fuslogvw.exe from Microsoft's Framework Tools. It shows all attempts and successes of assemblies your application binds to.
I suspect there's no line of your code that's causing this, since you say you aren't making use of the System.Windows.Forms types and the compiler error isn't pointing to a (useful) line of your code.
What I think is happening is that you're referencing a library which has a publicly-visible method or property that either returns a System.Windows.Forms.Control or takes one as a parameter. It doesn't matter whether you actually end up calling that method/property, the fact that it's publically visible means that your own code has to be able to resolve all the types that the library is using. If the library only used System.Windows.Forms internally, you wouldn't be experiencing this.
It also means just looking at the dependencies of the assemblies you're depending on may merely narrow down the list of suspects, since there could be some assemblies that depend on System.Windows.Forms internally (no problem) and the one troublemaking assembly that has a public parameter / return value of a type from the S.W.Forms assembly.
My suggestion is you just set up an empty project without a reference to S.W.Forms, then add each of your dependencies in turn and try to compile after each one.
I had the same error.
The problem was that I used a reference to a project, which uses System.Windows.Forms inside.
The solution is to add a reference to System.Windows.Forms also in your project.
Use something like NDepend or Reflector or the Object Browser to check the dependencies of the assemblies you depend on.
I cannot think of any other way given the info above.
I'm getting a strange warning:
The predefined type 'System.Runtime.CompilerServices.ExtensionAttribute' is defined in multiple assemblies in the global alias; using definition from 'c:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll'
There is no line number given, so it's hard to figure out what it's on about.
The compiler error code is CS1685
Are you using someone's dll (or your own) which had implemented this attribute (with exactly the same name) itself as a means of using some c# 3.0 features on pre .Net 3.5 runtimes? (A common trick)
This is the probable cause. Since it is using the correct one (the MS one in the GAC) this is not a problem though you should hunt down the other and remove it.
Expanding on ShuggyCoUk's (correct) answer
Truthfully it doesn't matter which version of the attribute is used (GAC, 3rd part, etc ...). All that matters is the C#/VB compiler can find some attribute with the correct name. The attribute serves no functional purpose in code. It exists purely to tell the Compiler "hey, this is an extension method".
You can safely ignore this warning.
I agree with ShuggyCoUk that the best course of action is to try to remove the offending dll. That may not be possible, though.
Another way to resolve the ambiguity that the compiler is complaining about is to change the Alias of the referenced dll. In your project, in the References folder, if you click on a referenced dll you will see the Aliases property. By default, this is "global", which allows you to do things like "global::SomeNamespace.SomeType". You might simply be able to change the alias to something else.
This fixed a problem I had where I needed to reference Microsoft.Scripting.Core.dll, but it contained some types that conflicted with mscorlib.dll. I changed the Aliases property to be "ThirdParty" instead of "global", and that fixed the warning.
I have the same problem.
In my case the problem was the assembly Mono.Cecil.
Migrating from local references to nuget, when i add NHibernate references the package automatically adds this reference.
This reference was removed, and compiled my project again.
Remove it and be happy!!
This image was taken from ILSpy ( http://i.stack.imgur.com/Qyd5o.png )
The compiler does not know which System.Runtime.CompilerServices.ExtensionAttribute
So it is using the defination from c:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll'
A .dll you are using might have the same extenstion.
I triggered this error by installing IIS with .NET 3.5 instead of 4.5 by accident.
Fix was to add 4.5 back in in "Add Features ..." in control panel.