I got an desktop application which uses a small DLL written in C# registered as an COM object to collect some infos from Active Directory. The app is written in C++, it works fine. I would like to write a small app in C# which would call the same registered DLL's methods (kind of testing tool), but can't figure out how to do this without referencing the COM DLL at compile time (I really need to use the COM registered dll)
I followed this article, managed to instantiate the object, but i cannot cast the instance to my interface created from IDL. Also the debugger knows the exact type of the instance with all members shown. I suspect this is due the DLL is loaded in the CLR as well.
Is this even possible?
thanks
You can't. The IDE will refuse to let you add a reference to the type library. You can fool it by using late binding. But that still doesn't fool the CLR, it won't create both a CCW and an RCW. You'll need a native client, like C++ or a scripting language to truly exercise the COM specific path.
There's just no point, just use the assembly reference directly and use normal C# code to test it.
You can consume a COM component from a C# project. The general steps are as follows:
Locate a COM component to use and register it. Use regsvr32.exe to register or un–register a COM DLL.
Add to the project a reference to the COM component or type library.
When you add the reference, Visual Studio uses the Tlbimp.exe (Type Library Importer), which takes a type library as input, to output a .NET Framework interop assembly. The assembly, also named a runtime callable wrapper (RCW), contains managed classes and interfaces that wrap the COM classes and interfaces that are in the type library. Visual Studio adds to the project a reference to the generated assembly.
Create an instance of a class that is defined in the RCW. This, in turn, creates an instance of the COM object.
Use the object just as you use other managed objects. When the object is reclaimed by garbage collection, the instance of the COM object is also released from memory.
For more information, see Exposing COM Components to the .NET Framework.
Detailed Article
I would suggest you use the .NET 4.0 dynamic type instead of all the mess of dealing with reflection in that article you mentioned
Related
I have a com dll written in vb6. I need to write c# code that wil get me a list of all the classes within it.
My Objective is to get the classes and generate the classes in .net with all the properties and create a mapping class.
I just need to get a list of classes from the dll.
Summary:
How can I get a list of all the classes in my com dll?
I would suggest using TLBINF32.dll. It is a COM component that ships with most versions of Windows. Make sure it is registered using regsvr32.exe from an elevated command prompt (along with your COM dll). Reference it in your .NET app (compiled to x86) and use the TLIApplication.TypeLibInfoFromFile method. From there you can traverse the type library of the COM component and get the classes, methods, interfaces, and properties exposed.
We use this library for various utilities.
Using reflection to walk the Interop for your COM DLL will give you classes and interfaces that a vaguely analogous to COM CoClasses and interfaces.
If quick and easy is what you're after, add your COM DLL as a reference in Visual Studio and use the code below to walk through the Interop assembly looking for classes. If it's a VB6 COM DLL everything is going to be IDispatch anyway, but you could optionally filter on objects with a CoClass, Guid or InterfaceType attributes on the types identified below (you didn't specify whether you were after classes or CoClasses).
var classes = Assembly.GetAssembly(typeof(MyComDLL.RandomTypeFromWithin))
.GetTypes()
.Where(type => type.IsClass);
If you're trying to really do this properly, the articles Dennis linked to in his comment are better, as is p/Invoke'ing LoadTypeLib and walking ITypeLib (the latter option being non-trivial).
I created a test COM project for .Net 4.0. Then I register it with the regasm:
RegAsm /codebase TestCom.dll /TLB
And it works correctly in JavaScript:
var app = new ActiveXObject("TestCom.TestClass");
app.Message1("123");
I want to use TestCom.TestClass from another C# project for .Net 3.5, but when I try to add the reference to this project, I get an error about higher framework version. The "Add Reference" dialog(section COM) only shows reference to a tlb file, not dll.
Is this the way it should be? When I try to add a reference to the tlb file I get the error:
"Add a reference to the .NET assembly instead"
How can I create an instance of TestCom.TestClass from another C# project for .Net 3.5?
The IDE can tell from the type library that you selected that the COM server is implemented in .NET. And it just refuses to let you add it, doing this doesn't make sense. It will work just as well, in fact better, when you add a reference to the .NET assembly instead.
It's not like you can't fool the machine, you can use late-binding with the dynamic keyword. No way for the IDE to interfere with that. But you are not actually testing the COM server the way an unmanaged client is going to use the server. The CLR will discover at runtime that the COM server is in fact a .NET server and shortcuts the plumbing. In other words, it will not create an RCW for the server. And the server won't create a CCW, this now works the exact same way it would have worked if you had added the assembly reference.
So it really does make no sense to do it this way. Just add the assembly reference and enjoy the many advantages you get from having IntelliSense support and static type checking. And test your COM server code the way you test any .NET library. What you don't test, and fundamentally cannot test, is the COM interop layers. Which is okay, it's not like it ever really is a problem. And if it is some for some mysterious reason then it is not like you can ever do something about it, the COM interop inside the CLR is a black box anyway.
All you need to do in addition to testing the server code is to perform an integration test. Just make sure that the actual unmanaged client can in fact use the server. You did, you already know it works well from Javascript.
Is it possible to use a VB6 class in C#?
I think you should just be able to add the library that contains your VB6 type as a reference in your C# project. Visual Studio will create an Interop Assembly on the fly, and you'll get access to all of the types in the VB6 library via Runtime Callable Wrappers.
The tool that creates the Interop Assembly is TLBIMP.EXE, and you can run this yourself if you want more control over the process, eg. if you want to create a Primary Interop Assembly that might be shared by multiple managed components.
You can use a compiled VB6 dll in a C# program by using COM Interop.
https://stackoverflow.com/questions/tagged/interop
As #Wayne states in his post (+1) it is absolutely possible.
I would go for a rewrite of your VB6 class:
If you have the VB6 source and the funding, I would recommend you to rewrite the class in C#.
Although VB6 may live forever :
Current support Statement for Visual Basic 6.0
Sure, you just need to make it a COM object.
Pretty much what it says on the tin. I've tried googling around but can't find anything helpful.
I'm trying to automate a process and part of that involves running forms/VBA code from an access 2003 database. What's the best way to call these from C#?
The Primary Interop Assemblies let you to automate Access 2003 from your C# application. In particular, you should be able to use commands like DoCmd.OpenForm and DoCmd.RunCode, allowing you to run your Access 2003 forms and VBA code.
Create the VBA code in a separate COM dll, and then you can use COM interop to call from C#
For instance, see SO question: Using a COM dll from C# without a type library.
Exposing COM Components to C#
You can consume a COM component from a
C# project. The general steps are as
follows:
Locate a COM component to use and register it. Use regsvr32.exe to
register or un–register a COM DLL.
Add to the project a reference to the COM component or type library.
When you add the reference, Visual
Studio uses the Type Library Importer
(Tlbimp.exe), which takes a type
library as input, to output a .NET
Framework interop assembly. The
assembly, also named a runtime
callable wrapper (RCW), contains
managed classes and interfaces that
wrap the COM classes and interfaces
that are in the type library. Visual
Studio adds to the project a reference
to the generated assembly.
Create an instance of a class that is defined in the RCW. This, in turn,
creates an instance of the COM object.
Use the object just as you use other managed objects. When the object
is reclaimed by garbage collection,
the instance of the COM object is also
released from memory.
I want to add a VC++ DLL reference into my C# Visual Studio project. But when I try to add it I see, "It is not a valid assembly or COM component".
Please suggest how I can use the VC++ DLL as a reference in a C# project.
There are two options for using a C++ DLL from C#: either COM interop, or P/Invoke. COM Interop involves creating a COM object in your C++ DLL, and then adding it as a reference. You can use the COM object like a C# object (for the most part) at this point.
P/Invoke allows you to call exported functions from C# (think calling standard Win32 API functions from C#). This is likely easier to set up, since all you need to do is export a function, however that could cause you to refactor your code in the C++ DLL, since it's not a very OOP way of doing things.
You can only use C++ components in C# when they have been prepared for use, for example by being written in C++/CLI or being written as a COM server.
If your component is a plain C++ dll you'll need to write some wrapper code, probably best is C++/Cli
I am not sure whether this solve..
run:
tlbimp /out:MyOldCom.dll MyNewAssembly.tlb
Then use it as you would any other assembly.
Please refer
http://msdn.microsoft.com/en-us/library/aa302324.aspx
http://msdn.microsoft.com/en-us/magazine/cc301501.aspx
ie)
One way is to package your DLL as a COM class and Another way is using DllImport