views:

375

answers:

4

I know a (vc++) ocx is an ActiveX control, and a (vc++) dll is a collection of functions. I've found that being called from a vb.net application, the catching of some exceptions could behave differently if the exception is being thrown from inside the ocx or inside a function that comes in a dll.

So my question is: From a point of view of a VB.net application, what are the main differences between using .ocx files and using .dll files?

+1  A: 

There is no difference. They are both dlls. You can rename a dll to anything and still load and use it using LoadLibrary, GetProcAddress.

m-sharp
While technically correct, (an OCX is a DLL) that's not a very useful answer. An ActiveX control exposes its interface through the IDispatch interface, which you can't access through GetProcAddress(). Not directly, anyway.
Ori Pessach
A: 
Joel Coehoorn
A DLL is not a COM object. It might implement a COM object, or several COM objects, or none.
Ori Pessach
Granted, but a dll created by vb6 and used in the same breath as an ocx almost always is.
Joel Coehoorn
Question has now been edited and says they are VC++ DLLs, so they might be COM DLLs or plain old DLLs. It does still seem likely that they are COM DLLs since they are being mentioned in the same breath as VC++ OCXs
MarkJ
+1  A: 

A DLL is a shared library. It's an OS level object - any process can load a DLL and call functions defined in it.

An ActiveX control is a COM object that implements specific interfaces that allows hosts to call its methods and embed it in their UI. There are certain minimum requirements on which interfaces an ActiveX control must implement to be embedded successfully in an application's UI. Since COM objects are typically dynamically loaded by a process, they are implemented as a DLL. A single DLL may implement one COM class or more.

Regarding exceptions - I'm not sure what differences you've observed, but a function is no different from a function implemented in your process's main .EXE file. An exception thrown in it should propagate normally according to the rules defined by your programming language's runtime environment.

An ActiveX method is different. Typically, it's called through something called an IDispatch interface. Rather than being a simple subroutine call, it's invoked by calling a method in the IDispatch interface (IDispatch::Invoke), with its arguments marshaled in a specific way (essentially, they're converted to standard types and packaged in a way that hides differences in calling conventions and data types between the implementation language of the main process and that of the ActiveX control.) IDispatch::Invoke interface then determines which method in the ActiveX the caller is trying to access, and routes it directly.

Exceptions are generally not propagated through the IDispatch interface. How your runtime environment deals with the error codes returned by IDispatch::Invokeis up to the implementer to decide, really. So you can reasonably expect not to have your expectations met when dealing with runtime errors and exceptions thrown in an ActiveX control.

Ori Pessach
I've set this answer as right, according to the following:* What I've experienced is that the .DLL exception is catched in a normal way, but the .OCX exception is not catched. * I've tried using try...catch blocks, Application.ThreadException handlers, AppDomain.CurrentDomain.UnhandledException handlers and with each value into Application.SetUnhandledExceptionMode, so I think the OCX exception is not being propagated through the IDispatch interface.
+2  A: 

An .ocx contains COM coclasses that follow the OLE automation contract. That contract has a well defined way to return errors to a client. Every method returns an HRESULT, a code that indicates whether the method succeeded or not. It is a simple integer, error codes are defined in the WinError.h SDK header file. It also supports getting context info about the error through the IErrorInfo interface. The COM interop support in the CLR ensures that a failure code is translated into a comparable Exception.

No such standard exists for code in C/C++ DLLs. If it throws an exception at all, it is almost always something nasty like an AccessViolation. The P/Invoke marshaller makes sure these exceptions are caught and translated. You'll invariably get very little useful info out of such an exception beyond "it didn't work". You should let these exceptions terminate your program, you cannot meaningful recover from it.

Hans Passant
+1 This is the best explanation IMHO. Although a C/C++ DLL could still be a COM DLL, question isn't totally clear about that
MarkJ