Microsoft Fakes "Assembly not supported" - visual-studio

I am attempting to add a Fakes assembly (in Visual Studio 2012 Ultimate) for an library that I reference in my code so that I can test independently of the libraries implementation. The the problem I'm having is that when I right click the referenced assembly and click "Add Fakes Assembly" I receive the message:
"Assembly not supported
Fakes does not support this assembly."
I've tried Googling this message but get 0 results if I put it in quotes and nothing relevant if I don't. I thought this was quite strange as you would expect someone else to have run into this issue at some point but anyway...
After giving up on searching for the message I tried searching for somewhere that might tell me what types of assembly Microsoft Fakes does support but this also proved fruitless.
I guess my question is: Does anyone know what types of assembly Microsoft Fakes does/doesn't support.
I've included some information about the assembly I'm referencing in case anyone knows why this one in particular isn't supported:
-Its a COM Interop assembly.
-Its an ActiveX component.
-It isn't strongly named.
Any leads at all would be greatly appreciated.

To be honest, the things you mentioned probably aren't the problem. It's entirely possible to fake Excel interop classes, for instance (not that you can use them!).
But if you take a look at what thing's don't support fakes, such as sealed classes, which don't allow stubs because stubs require inheritance, and some reflection classes which restrict shims, it's clear that some classes will have neither, thereby allowing a dll to have no fakeable components. Not much you can do there.
Additionally, Shims cannot be used on all types from the .NET base class library mscorlib and System. says MSDN.

Related

Is there any class count limit in MFC project compiled with /CLR

With the risk to fall into too specific question...
Given a C++ MFC (mixed, not shaked) project compiled with /CLR, I have 200 classes already defined.
When I add a new empty class to this project, an error raises when I compile and execute in debug mode.
An unhandled exception of type 'System.IO.FileLoadException' occurred
in Unknown Module.
Additional information: Could not load file or assembly 'ProjectA,
Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its
dependencies. Could not find or load a type. (Exception from HRESULT:
0x80131522)
ProjectA is the name of the MFC project itself. There is no reference to any ProjectA assembly on project configuration, and there is no reference to another custom assembly.
This project only have references to some .NET Framework assemblies, in order to allow that some of custom defined classes in the project can use CLR classes.
Then, the question is...
Do you know whether there is any limitation of class number on a MFC C++ project?
EDIT:
As I say in comments, in release mode the compilation succeed without errors.
Also, I clean, build, clean, close Visual Studio, reboot computer... and the problem still appears.
If I keep in 200 classes, there is no error. When I go to 201, the error appears.
Currently I'm trying to reproduce in a new default MFC project, adding classes till arrive to 200, to confirm that there is a real limitation.
EDIT 2: ERROR FIXED
Great. #MSX and #frymode show me how avoid the error with his comments.
In the Visual Studio development environment (source / source):
Open the project's Property Pages dialog box.
Click the C/C++ folder.
Click the Code Generation property page.
Modify the Enable String Pooling (/GF) property.
Thank you guys!
The /GF hack is a known workaround for this problem. It is however not a correct one, you are putting a band-aid on a heavily bleeding wound. Pretty important that you heal the problem instead of putting a patch on it, this heavily affects the way your program runs at runtime as well.
The problem maker is the <Module> class, an internal class that the C++/CLI compiler generates. You can see it with ildasm.exe or a good decompiler. This class is required as a home for declarations in your program that are not class members, valid in native C++ but not supported by the CLR. Which demands that every variable or function declaration is a member of a class. The C++/CLI compiler solves it by moving such a declaration into the <Module> class.
There is however a limit on the number of members in a class, they are represented in the metadata of the .NET assembly with a metadata token. An index into other tables. The upper byte identifies the table number, the lower bytes are the index in the table.
You exceeded that limit. This is bad.
A problem with the /clr compile option is that it works too well. It is capable of compiling any C++03 compliant native C++ code to MSIL. Such code will be just-in-time compiled to machine code by the jitter, just like normal managed code. It is however not verifiable code and it doesn't act like managed code at all, you can blow up your program with pointer fumbles just as easily. And above all, it is not code that's optimized with the native C++ back-end. Only the jitter optimizer has a shot at improving that code, it cannot do nearly the quality job that the native C++ optimizer can do, given that it runs with a hard upper limit on how much time it can spend on doing that job.
Have a look-see with a decompiler to see what ended up in that <Module> class. That's going to be overwheliming at first, you know you've got a big one right now. You fix this problem by spending more time segregating the code into the managed parts and the native parts. Where the native code should be compiled without /clr in effect. It is a per-source file setting, you can even switch back-and-forth in a single source code file with #pragma managed. The simplest way to segregate is by keeping your native code in its own library or DLL.
This link shows that there's no limit to the number of types you can have in a namespace (not a project). Considering, that a namespace can be split across different assemblies, you could, at least in theory, have an unlimited number of types. However, this post affirms that the maximum number of classes in a .DLL
is 16777215. Probably, you'll run out of memory before you reach that number of classes :)
Just for information: there seems to be a limit to the number of fields per class, though.
P.S.:
Here's the solution to your problem taken from this link
Open the project's Property Pages dialog box.
Click the C/C++ folder.
Click the Code Generation property page.
Modify the Enable String Pooling property.

COMVisible class in VS 2010 assembly still not visible through com

I created a VS 2010 class library. Marked the assembly for Com Visibility. Signed the assembly with a strong key. Created my class, have my entry point method available.
The library works fine from a test project in C#.
I regasm the class library to gac, via:
c:\windows\microsoft.net\framework\v4.0.30319\regasm testdll.dll /tlb: testdll.tlb /codebase
Include the tlb file as a reference in my VB6 project. I find it through resources 'browse' so its there.
When i try to instantiate the class... its empty. the public method that should be available via the public class doesn't show.
Dim objTest as testdll.testclass
set objTest = new testdll.testclass
objTest.testmethod <--- this 'testmethod' doesn't display in intellisense... nothing does.
In addition i tried calling the 'testdll.testclass' via CreateObject, i get the error "ActiveX component can't create object"
Now i have other projects i've done COM visibility for and i've tried comparing the difference, but i don't see any. I can't understand why it isn't working.
Any clues??? tx very much.
Just use an interface... one you define or to use the [ClassInterface(ClassInterfaceType.AutoDual)]
there are comments online you can find that indicate not to use autodual, but if you control the complete usage of your library, it seems like an 'ok' way to go.
I tried all sorts of ways to simulate / understand why my one project didn't need an interface to be visible by an vb project, without success. i had originally thought perhaps possible that it was because that project implemented an IDisposable Interface (the ONLY interface used in the C# projects that is com visible) but that didn't turn out to be the reason. Anyway I don't want to waste anyone else's time on this. thanks for the responses.
this link provides ample information on the subject:
http://anturcynhyrfus.blogspot.com/2011/03/creating-com-visible-c-component.html

Getting up and running with code contracts

In VS2010 and .NET 4.0, I see the shortcuts in intellisense for adding contracts to my code (Eg cr, crr) but when I tab to add these in, the code (Such as Contract.Requires) does not have the valid assembly so there is no intellisense (The type can't be found basically).
How exactly do I get up and running with code contracts?
EDIT: All the methods exist in System.Diagnostics.Contracts, but I thought that I would be using attributes throughout? Also, there are so many different .dlls for the contracts available!
Thanks
The assembly is just mscorlib - and Contract is in the System.Diagnostics.Contracts namespace.
<plug>
For some more information about Code Contracts, you could buy the second edition of C# in Depth and read chapter 15. (That chapter was available free, but isn't now I'm afraid.)
</plug>
Or of course you could read the docs too, as they're pretty good :)
If you find you're missing the System.Diagnostics.Contracts namespace, it's worth checking that you really are targeting .NET 4 - if you create a .NET 3.5 project in VS2010, that won't have Code Contracts available (without adding an explicit assembly reference, anyway).

How to fix "Unexpected error (32801)" when compiling VB 6 program?

I have to maintain an old VB 6 ActiveX DLL called by another third-party program for which I have no sources. This DLL works and compiles fine against the API of said program for about 6 years and 3 major versions.
But now when I try to compile the DLL against a new major version the mentioned error occurs. It seems the error occurs before "my" code is called so there´s no use debugging or logging. The only remedy was to compile w/o binary compatibility which is no real option. My Google search turned up quite some people with the same problem but no solution.
Does anybody here know how to fix this issue ?
I finally figure out how to diagnose VB6 error 32801 in a systemic way.
My theory is When the VB6 compiler is creating a project or binary compatible library, the compiler decompiles the type information from the referenced library. Error 32801 occurs the source code's type information is not the same as the referenced library.
There is a tool called OLEView. This tool can decompile the COM type information into an IDL text. What I do is decompile the referenced library in to IDL and take the last good build of the failing library. Most times it is a build server version but the build does not work on a developer workstation. Decompile the last good build. Use a text comparison tool, like WINMerge, and find the differences between the type libraries. The differences make it easy to track down the problem.
Depending on the difference will determine how to correct. Mitigation can be done by either correcting the reference DLL, or by source code correction, or source code references.
It sounds like one of the types in the interfaces defined in your new DLL is different from one in the previous DLL. I'm deducing you use types defined in the third party program in your public interfaces of your DLL. It sounds to me like the third party has changed the definition of one of the types but kept the name and GUIDs the same. You could use something like OLE/COM Object viewer to check whether that's true. If it is true then you can complain to the publisher of the 3rd party program. Do you have enough political power to succeed?
Bruce McKinney, the guru who wrote Hardcore Visual Basic 6, ran into the same issue with a structure in a type library, where he changed some of the member types. The only fix he could find was (essentially) to break binary compatibility - and that's after some correspondence with the VB6 compiler team, who he knew fairly well. I don't think anyone else could do better.
There is a discussion about this error on devx.com that seems to indicate that the problem stemmed from Microsoft's Scripting Runtime (scrrun.dll).
FileSystemObject compatibility Unexpected error (32810)
Does your DLL reference that library? If so, can you remove the reference (e.g., replace FileSystemObject functionality with intrinsic VB file handling functions and/or API calls).
Are any of the files associated with the core project being compiled marked as Read-Only (i.e. not checked out of SourceSafe or similar repository)?
*.exp
*.vbw
*.lib
---------------------------
Microsoft Visual Basic
---------------------------
Unexpected error (32810)
---------------------------
OK Помощ
---------------------------
This the message I was getting trying to reference in VBIDE an old OCX that has been recompiled recently.
After somewhat long research the offending lines of code causing this error appeared to be
Property Get MouseActivate() As BookmarkEnum
Just changed this to
Property Get MouseActivate() As Boolean
. . . and the error was gone.
BookmarkEnum is an enum from ADO. Our build server is Server 2003 and my dev machine is Win10. The project references ADO 2.8 but apparently this typelib has some differences on Server 2003 vs Win10

Strange VB6 build problems (related to nlog)

This I think is related to my use of the nlog C++ API (and my question on the nlog forum is here); the purpose of my asking this question here is to get a wider audience to my problem and perhaps to also get some more general ideas behind the VB6 IDE's failure to build in my particular scenario.
Briefly, the problem that I am having is that I am having trouble building VB6 components which reference unmanaged C++ components which have calls to nlog's C\C++ API (which is defined in NLogC.DLL). The build problems are not occurring during compile time, they are occurring when the binary is being built which suggests to me that it's some kind of linker type problem? Don't know enough about how VB6 binaries are produced to tell. The VB6 binary is produced, but it is corrupted and crashes shortly after it is invoked.
Has anyone had any similar experiences with VB6 (doesn't have to be related to nlog or C++)?
edit: Thanks for all the responses to this rather obscure problem. Still no headway unfortunately; my findings since I posted this:
'Tweaking' the compile options doesn't appear to help in this problem.
Adding a reference to the nlog-enabled C++ component from a 'blank' VB6 project doesn't crash it or cause weird build problems. So it isn't a 'native' VB6 issue, possibly an issue with the interaction between nlog and the various components and 3rd party libraries used by other referenced components?
As for C++ calling conventions: the nlog-enabled C++ component is - as far as I can see - compliant to these conventions and indeed works fine when referenced by VB6 as long as it is not making any nlog API calls. Not sure if the nlogc.DLL itself is VB6 compliant but I would have thought that that is immaterial since the API calls are being made from the C++ component; VB6 shouldn't know or care about what the C++ component is referencing (that's as far as my understanding on this goes...)
edit2: I should also note that the error message obtained during build is: "Errors during load. Please refer to "xxx" for details". When I bring up the log file, all that there is in there is: "Cannot load control xxx". Interestingly, all references to that particular control disappears from that particular project resulting in compile errors if I were to try to build again.
Got around the problem by using NLog's COM interface (NLog.ComInterop.DLL) from my unmanaged C++ code. Not as easy to do as the C\C++ API but at least it doesn't crash my VB6 components.
I would try tweaking some of the Compile options found in the Project, Properties menu, Compile panel to see if they yield any additional hints as to what is going wrong.
For example if you compile the executable to p-code rather than native code does it still crash on startup.
What error message do you get when you run your compiled binary?
I doubt the compiler/linker is the problem: project references in a VB6 project are not linked into the final executable. A project reference in VB6 is actually a reference to a COM type library (which may or may not be embedded in a .dll or other binary file type). Project references primarily serve two purposes:
The IDE extracts type information from the referenced type libraries which it then displays in the Object Browser (and in the Intellisense drop-down)
At compile-time, the compiler extracts the type information stored in the referenced libraries, including the CLSID of each class that you instantiate, and embeds this data into the executable. This allows your executable to create instances of classes contained in the libraries that you referenced.
Note that the compiled binary doesn't link to any code in the referenced libraries, and it doesn't even contain the filenames of the referenced libraries. The final executable only contains the CLSID's and other type information that it needs to instantiate COM objects at run-time.
It is much more likely that the issue is with NLog, or with how you are calling it from your code, rather than something gone awry in the VB6 compile process.
If you think it might be a linker problem, this should crash it the same way:
create a new standard project (of any kind)
add a new module and copy the "declare"-statements into it
compile
If it doesn't crash it is something else.
It would help an exact description of the error or a screenshot of what going on.
One thing to check is wherever NLogC.DLL or the C++ DLL you built have the correct calling convention defined. Basically you can't have the DLL function names mangled or use anything but the STDCALL calling convention. If the C++ DLL has not been created with those two things in mind then it will fail to work with VB6.
MSDN Article on Calling convention.
"Cannot load control xxx" errors can be caused by .oca files which were created from a different version of an .ocx than currently used. If that is the case, deleting the .oca files helps.

Resources