Registration Free COM errors with EXE - c#

I'm trying to use COM functions exposed by an EXE. I've created a C# project using Visual Studio 2010 (on a windows7/x64 machine) and added the reference to that EXE, then set the Isolated flag to true. When I build the solution, I get errors for each of the classes that it exposes.
Problem isolating COM reference 'FNCClient11Lib': Registry
key
'HKEY_CURRENT_USER\SOFTWARE\CLASSES\CLSID{e49b30c9-6d7e-48f5-91da-f2f0414c6a13}\InProcServer32'
is missing value '(Default)'.
These entries don't exist in the registry in that location but DO exist here (below)
HKEY_CURRENT_USER\Software\Classes\Wow6432Node\CLSID{E49B30C9-6D7E-48F5-91DA-F2F0414C6A13}
Is there any way I can point this to the right location in the registry when building?
Can I reference an EXE? All the examples I've seen so far reference DLLs only.

This problem occurs when the type library contains classes that are marked as 'uncreatable' in the COM interface. You can check this by using the OLE/COM Viewer (as Admin), navigating to the type library that causes the problem, opening it and look up the CoClass definitions. If the one using the reported uuid is declared 'uncreatable', you got it. Also, in the VS object browser, these clases don't expose a constructor in the interface.
My solution was to rebuild the COM component with a public constructor for these classes but of course this is only possible if you have the sources.
Finally, there may be other reasons for this symptom though ...

Related

Is it possible to reference a COM DLL without registering itself?

I have activated COM registration free DLL when deploying the application. In addition, I have set the Properties->Linker->Register Output to NO in my build process. However now my application which references the DLL no longer builds because it cannot find the reference. So my question is that is it possible to build the application that references the DLL without registering the dll?
Thanks!
You left no breadcrumbs to guess why registration is required to build your code. This is not normally necessary. One random guess is that you are using the Isolated property for a reference in a C# project for a COM component written in C++. Which is a very nice feature, it automatically generates the manifest entries so the program can run reg-free.
But those manifest entries need to come from somewhere if you don't write them yourself. Which is the registry if you use the Isolated property. Chicken-and-egg problem here, you have to register it so it can run unregistered :)
Keep in mind that you use reg-free COM on the user's machine, it isn't important on your dev machine.

Adding a VB6 reference in Visual Studio gives "Type library importer encountered an error during type verification"

I am in the process of convering a rather large project written in VB6 into C#. Given the size of the project being moved, it is being done in phases over the course of 18-months. I am running into an issue with adding a reference of a VB6 ActiveX dll to a .Net project.
If you follow exactly these steps, you too should be able to recreate the problem.
I have written an interface in .Net that is COM visible:
<ComVisible(True)>
Public Interface ITestInterface
Property A As String
Function TestMethod() As String
End Interface
By selecting "Register for COM interop" in Compile tab of project properties, you get a TLB file.
I've created a VB6 project that references this TLB and a class that implements the interface exposed.
Implements ITestInterface
Private mA As String
Public Property Get ITestInterface_A() As String
ITestInterface_A = mA
End Property
Public Property Let ITestInterface_A(ByVal value As String)
mA = value
End Property
Public Function ITestInterface_TestMethod() As String
ITestInterface_TestMethod = "From VB6"
End Function
If I set the Component tab of project properties in VB6 to use "Remote Server Files" then a TLB is automatically created when compiling. I can view that TLB in OleView and see the following (in addition to the details of the concrete implementation done in VB6 of the interface defined in the .Net project):
// typelib filename: TestVB6Interface.dll
[
uuid(**EF005573-BFC7-436D-A382-F906CA09F94A**),
version(3.0)
]
// ... some other stuff
// TLib : // TLib : : {79EC733A-0267-4506-8D38-C4D4655E0755}
importlib("SimpleDotNetLibrary.tlb");
Now, I create a completely new .Net project. If I add a reference to the VB6 dll, I get the following error:
Could not resolve COM reference "ef005573-bfc7-436d-a382-f906ca09f94a" version 3.0. The type library importer encountered an error during type verification. Try importing without class members.
However, if I launch a Visual Studio Command Prompt and run the following:
tlbimp TestVB6Interface.tlb /out:TestVB6Interface.MyInterop.dll
Then I can add that dll as a reference in my .Net solution and it works perfectly fine.
My question. What is tlbimp doing on the command line that is not being done when I just add the reference directly? When the message in Visual Studio says "try importing without class members" how exactly do I do that within Visual studio? I know how to do that in tlbimp.
I apologize for the wall of text, but I wanted to describe the situation as best I could keeping the information I felt was relevant.
The Visual Studio IDE definately takes a different path when registering DLLs for COM Interop then it does when running the command line tools from a command prompt.
I doubt that Microsoft has documented this anywhere. However, my years of experience have proven this to be the case. I once ran into a situation in which a "regsvcs" command from the .NET 2.0 Framework would actually cause an infinite loop. If you Google it you'll probably find others that have had this problem. I was able to make it one step further by using the VS IDE to perform the COM registration of a .NET Serviced Component. However, it inevitably ended in error. The error was a step forward over the infinite loop. Either way it proved to me that the VS IDE takes a different code path / business logic when dealing with COM Interop and registry entries.

Registering assembly for Interop assembly with COM visible interfaces only gives warning MSB3214

I have a project with a single interface marked with ComVisible(true). If I build the project, I get warning MSB3214: "" does not contain any types that can be registered for COM Interop.
If, however, I create an empty class, give it a default constructor and mark it with ComVisible(true), I do not get warning MSB3214. I see the registered class but I do not see the interface in my registry.
What am I missing?
This is by design, in spite of Jays link. Regasm.exe only writes registry keys for concrete classes that implement an interface. The ProgID and the CLSID keys. COM does have registration for interfaces (HKCR\Interfaces) but only proxies get registered there. .NET has no mechanism to create proxies.
An assembly with only interface declarations is only useful to create a type library, allowing other projects to implement them. Creating a type library is not a problem, use Tlbexp.exe
Looks like it could be a Visual Studio 2008 bug reported in July 2008: VS creates no type library for a project containing solely C# interfaces (MSB3214)
There are no listed workarounds.
In a response data Sept 2009 Microsoft they were (presumably) able to fix the issue:
We were able to fix this issue and the
bug will be available in the next
release of the product.
(let's assume he meant the bug fix will be available in the next release)
I couldn't find any evidence the bug was fixed.

How to create a generic use library

I have an image editor user control(c# .net v2.0). Its used in thousands of computers as an activex component. I want the component also be available for windows forms and possible other uses.
For activex usage i add <object> tag in html code and call the component with clsid(a static guid). So if i build and distribute a newer version it works without changing any client code.
I want windows forms to be able use the same distributed libraries. And they should not reference a specific version so i can update the component without changing the programs that use it.
I use regasm to register for com. But i dont know how to reference it from visual studio(like referencing with clsid?)
May be in visual stuido when i choose add reference and select COM tab i shuld see my component in the list.
note: i tried to add the assemly to the global cache using these lines but it did not work out-or i coulnt understand if anything has changed :)
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\tlbexp" ImageEditorComp.dll /out:ImageEditorComp.tlb
regasm /tlb:ImageEditorComp.tlb ImageEditorComp.dll
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\gacutil" /I ImageEditorComp.dll
Any suggestions appreciated,
Regards
This is not possible, you'll invoke the infamous and dreaded DLL Hell problem. A stone cold hard rule in COM is that you have to change the [Guid] attribute values on public interfaces when you make a breaking change in either the publicly visible interfaces or the implementation of them. Changing the guids ensures that you don't overwrite the registry keys of an old version of your component when you use Regasm.exe. Existing programs that use your component and were not recompiled to use the latest version will continue running without problems. The typical outcome of DLL Hell is a nasty hardware exception like AccessViolation, very difficult to troubleshoot.
None of which applies in your specific case here. There is no point in trying to use the component through COM. It is a .NET assembly, just add the reference to it directly. The IDE will in fact stop you from adding a reference to the interop library. But not the .tlb. The GAC keeps you out of DLL Hell, assuming you properly increment [AssemblyVersion].
I figured out a solution.
To explain step by step:
1- Create the component with all needed properties for com.(Sign the assembly, use interfaces for com, make assembly com visible)
On the client machine
2- Register the assembly with regasm(i recommend adding safety flags too).
3- Add the assembly to the global cache using gacutil(or msi installer)
I figured out when you call a specific version of an assembly gac is searched in the first place so if its installed in GAC, referenced codebase path is never used.
When using as activeX you address the component with GUID. Since regasm adds the assembly name and version the GUID is representing, web browser directly uses component from GAC.
When using from a desktop application, reference the assebmly directly and set copylocal property to false. Similarly, in the client machine windows will find the assembly located at GAC itself.
Here is a useful link about the subject.
http://www.simple-talk.com/dotnet/visual-studio/build-and-deploy-a-.net-com-assembly/
Hope it saves other peoples time :)

C# wrapper interface error: E_NOINTERFACE

I am trying to produce a C# wrapper for a COM object that I have (named SC_COM.dll), but am having some issues linking it with Visual Studio 2008 (running Vista). I need to do this registration-free with the COM DLL--I'm using a manifest file to let Visual Studio know about SC_COM.dll, and that appears to be working. I used TblImp.exe to generate a type library (SC_COMtlb.dll) that I'm referencing in Visual Studio 2008 so I can do early binding with the DLL that I need. The DLLs are both in the same directory as the manifest and the executable.
Here's the issue: When I instantiate the object and try and call one of its methods in C#, it throws the following error:
Error detected: Unable to cast COM object of type 'SC_COMtlb.SCAccessObjClass' to interface type 'SC_COMtlb.ISCUploader'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{C677308A-AC0F-427D-889A-47E5DC990138}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
I'm not entirely certain what this error means--I've done a search on the error code, and it appears to be a relatively general C# error. So am I going about linking the COM object the wrong way here, or is there some other important step I may be missing?
I should probably note that I'm not entirely sure how the type library (S\C_COMtlb.dll) that I produced knows where the actual COM DLL is, since it's not registered with the system--I assume it just looks in the same directory. Could this potentially be the issue, and if so, how can I better link the two?
Try adding this to your App.exe.manifest:
<comInterfaceExternalProxyStub
name="ISCUploader"
iid="{C677308A-AC0F-427D-889A-47E5DC990138}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{PUT-YOUR-TLB-GUID-HERE}" />
Where TLBID can be found from your Visual Studio generated Native.Namespace.Assembly.Name.manifest, looking like this:
<typelib tlbid="{A-GUID-IS-HERE--USE-IT}"
version="1.0" helpdir="" resourceid="0" flags="HASDISKIMAGE" />
I was banging my head against this for quite some time, but I found these helpful references and pieced it together and it's working for me:
Why do I get E_NOINTERFACE when creating an object that supports that interface?
Registration-Free Skype4Com and multithreaded apartment
Registration-Free Activation of COM Components: A Walkthrough
Which version of Windows? Since Windows Vista, an internal manifest overrides an external manifest. By default, C# executables have internal manifests, which means that your whatever.exe.manifest file will be ignored.
If you go to the properties page for your C# EXE, you'll see there's an "Icon and manifest" section on the "Application tab". Set "Manifest" to the name of your manifest file, and it'll be embedded instead of the default one.
If that doesn't work, you might have to do some post-build steps with MT.EXE in order to merge your external manifest with the default internal one and to put the merged manifest back into the .EXE file.
the error code means that Visual Studio thinks that a certain object is supposed to implement a certain interface, but when I tries to "connect" to that interface the object responds that it doesn't know about it.
I would guess that the problem is in SC_COM.dll. TLBIMP.EXE extracts class and interface information from metadata stored within the DLL and builds wrappers for the class.
For example, if SC_COM is written in C++, this could happen if the creator of the DLL indicated in the IDL file that a class implements that interface, but the actual code doesn't support that interface.
Here's another common source of problems this DLL might have: sometimes you have a class implementing an ISomething2 interface which derives from an ISomething interface, but the class implementation to only recognize ISomething2. If you implement a derived interface, you must recognize its base interface as well. This is a common mistake.
Do you have (and control) the source code for the DLL?

Categories