Copied for longevity
(from the great Igor Tandetnik):
The difference is not between ODL and IDL - you can change the file
extension to .idl and it will behave exactly the same way. The
difference is in the file structure.
The way MIDL compiler works, .h file is generated based on the
declarations _outside_ the library block. TLB is generated based on the
declarations inside the library block. The usual approach is to defined
all the interfaces (and structs and enums) outside the library block,
then mention them inside (usually as part of coclass statement). This
way, you would get them both in the header file and in TLB.
Your ODL file, I bet, defines everything inside a library block.
(from the great Alexander Nickolov):
If you deselect ODL mode for your MFC project, you must also
rename it with IDL extension since it's no longer an ODL file.
ODL = Object Description Language - only describes type libraries
IDL = Interface Definition Language - describes both interfaces and
type libraries (contains ODL as a subset).
Historically, initially IDL coudn't be used for type libraries, so
Microsoft invented ODL. Later they joined the two languages
under the IDL name. IDL itself is inherited from OSF DCE RPC
spec and extended to support COM interfaces. It does contain
the original IDL as a subset - you can still use it to define RPC
interfaces (e.g. don't specify [object] for the interface).
Showing posts with label com. Show all posts
Showing posts with label com. Show all posts
Wednesday, August 22, 2012
Tuesday, August 23, 2011
C++/CLI ActiveX automatic registration
I've been working on an ActiveX control written in C++/CLI recently and I thought I'd share the COM registration function ([ComRegisterFunction()] attribute) I've written (which is called by regasm.exe when you're registering the assembly for COM Interop).
It does the following:
Creates the necessary keys to register as an ActiveX control.
Adds in the codebase keys so there is no need to pass the /codebase flag to regasm.exe.
Please note, if you're not including oleidl.h as part of your include hierarchy (which I am as I'm using the Windows SDK), then you'll need to define the following constants:
It does the following:
Creates the necessary keys to register as an ActiveX control.
Adds in the codebase keys so there is no need to pass the /codebase flag to regasm.exe.
Please note, if you're not including oleidl.h as part of your include hierarchy (which I am as I'm using the Windows SDK), then you'll need to define the following constants:
// Ref: http://msdn.microsoft.com/en-us/library/ms678497.aspx const int OLEMISC_RECOMPOSEONRESIZE = 1; const int OLEMISC_CANTLINKINSIDE = 16; const int OLEMISC_INSIDEOUT = 128; const int OLEMISC_ACTIVATEWHENVISIBLE = 256; const int OLEMISC_SETCLIENTSITEFIRST = 131072;Credit is given to the authors of the CSActiveX control upon which this code was originally based.
//
// we need to add some extra registry keys on top of the regasm.exe generated
// keys. this is because we are an ActiveX control (not just a plain COM control)
// and as such require certain keys and values to be present.
//
// we also add in the codebase entries (instead of passing /codebase to regasm.exe)
// this is so we avoid the overkill warnings that regasm.exe generates.
//
// as such to register this .NET assembly as a fully fledged ActiveX control
// we need to run:
//
// regasm.exe /tlb
//
void FTEngine::Register( Type^ t )
{
try
{
// Open the CLSID key of the control
RegistryKey^ keyCLSID = Registry::ClassesRoot->OpenSubKey( "CLSID\\" +
t->GUID.ToString("B"), true );
//////////////////////////////////////////////////////////////////////////
// Set "InprocServer32" to register a 32-bit in-process server.
// InprocServer32 =
// Ref: http://msdn.microsoft.com/en-us/library/ms683844.aspx
//
RegistryKey^ subkey = keyCLSID->OpenSubKey( "InprocServer32", true );
if( subkey )
{
// .NET runtime engine (mscoree.dll) for .NET assemblies
subkey->SetValue( nullptr, Environment::SystemDirectory + "\\mscoree.dll" );
// setup codebase flag as we're not in the GAC
subkey->SetValue( "CodeBase", Assembly::GetExecutingAssembly()->CodeBase );
// setup the version specific codebase flag
Version^ ver = Assembly::GetExecutingAssembly()->GetName()->Version;
subkey = subkey->OpenSubKey( String::Format( "{0}.{1}.{2}.{3}",
ver->Major, ver->Minor, ver->Build,
ver->Revision ), true );
if( subkey )
{
// setup codebase flag as we're not in the GAC
subkey->SetValue( "CodeBase",
Assembly::GetExecutingAssembly()->CodeBase );
}
}
//////////////////////////////////////////////////////////////////////////
// Create "Control" to identify it as an ActiveX Control.
// Ref: http://msdn.microsoft.com/en-us/library/ms680056.aspx
//
keyCLSID->CreateSubKey( "Control" );
//////////////////////////////////////////////////////////////////////////
// Create "MiscStatus" to specify how to create/display an object.
// MiscStatus =
// Ref: http://msdn.microsoft.com/en-us/library/ms683733.aspx
//
subkey = keyCLSID->CreateSubKey( "MiscStatus" );
int nMiscStatus = OLEMISC_RECOMPOSEONRESIZE +
OLEMISC_CANTLINKINSIDE + OLEMISC_INSIDEOUT +
OLEMISC_ACTIVATEWHENVISIBLE + OLEMISC_SETCLIENTSITEFIRST;
subkey->SetValue( "", nMiscStatus.ToString(), RegistryValueKind::String );
//////////////////////////////////////////////////////////////////////////
// Create "ToolBoxBitmap32" to identify the module name and the resource
// ID for a 16 x 16 bitmap as the toolbar button face.
// ToolBoxBitmap32 = .,
// Ref: http://msdn.microsoft.com/en-us/library/ms687316.aspx
//
subkey = keyCLSID->CreateSubKey( "ToolBoxBitmap32" );
// If you want different icons for each control in the assembly you
// can modify this section to specify a different icon each time.
// Each specified icon must be embedded as a win32 resource in the
// assembly; the default one is at the index 101, but you can use
// additional ones.
subkey->SetValue( "",
Assembly::GetExecutingAssembly()->Location + ", 101",
RegistryValueKind::String );
//////////////////////////////////////////////////////////////////////////
// Create "TypeLib" to specify the typelib GUID associated with the class.
//
subkey = keyCLSID->CreateSubKey("TypeLib");
Guid libId = Marshal::GetTypeLibGuidForAssembly( t->Assembly );
subkey->SetValue( "",
libId.ToString("B"),
RegistryValueKind::String );
//////////////////////////////////////////////////////////////////////////
// Create "Version" to specify the version of the control.
// Ref: http://msdn.microsoft.com/en-us/library/ms686568.aspx
//
subkey = keyCLSID->CreateSubKey( "Version" );
int nMajor, nMinor;
Marshal::GetTypeLibVersionForAssembly( t->Assembly, nMajor, nMinor);
subkey->SetValue( "",
String::Format( "{0}.{1}", nMajor, nMinor ) );
}
catch( Exception^ ex )
{
LogException( ex );
throw;
}
}
Subscribe to:
Posts (Atom)