 |
|
 |
the page one and page two links are not working
|
|
|
|
 |
|
 |
http://www.codeproject.com/KB/COM/COM_from_scratch_1.aspx
http://www.codeproject.com/KB/COM/COM_from_scratch_2.aspx
|
|
|
|
 |
|
 |
Hi, i cannot load these COM dlls in .NET, usually when I add COM dlls (MS Office etc) from VS 2005 --> Add reference VS takes care of all the interop stuff and loads the COM Dll in my C# project, but i when i add these dlls it says that the DLLs are not valid COM objects....ne ideas?
|
|
|
|
 |
|
 |
You have to create the .idl file. Then using MIDL compiler it will produce .h,.c and .tlb file. After that u hve to convert .tlb to create the metadata using TLBIMP tool to produce .dll which can be use directly inside .net....I think there was alternative way to do.
|
|
|
|
 |
|
 |
Can any one refer me the source(on web) from which i can learn and unerstand all com classes and how the interact and work. But before refering me the source keep in mind that i am new to com
|
|
|
|
 |
|
 |
I have loaded into lpStorage(of type IStorage) a regular file. Then I have opened the data into pStream(of type IStream). I am now trying to load pStream into pPersistStream(of type IPersistStream). Since pStream was loaded from a regular file, it does not have an associated CLSID.
So when I do the following,
hr =CoCreateInstance(clsid,NULL,CLSCTX_ALL,IID_IPersistStream,(LPVOID*)&pPersistStream);
What should the value of clsid be?
Thanks for your help in advance!
|
|
|
|
 |
|
 |
Hi,
As you may know a GUID is used to identify a component and it is called a class identifier.
Components publish their filenames(i.e dll filenames) indexed by CLSIDs in windows Registry.
CoCreateInstance looks up the filename by using the CLSID as the key.
This function takes a CLSID,creates an instance of the coresponding component, and returns an interface for the instance of the component.
So the clsid should be the class identifier of the component that you want to create an instance.
The following are a summary of the parameters used by this function:
in parameters:
1-The first parameter is the CLSID of the object.
2-second parameter is used to aggregate the object as part of another object.
3-The thrid parameter specifies the execution context of the object.
4-The 4th parameter is the IID(interface Id) of the requested interface.
out parameter:
5-The last parameter which is an out parameter is an interface pointer to the object.
|
|
|
|
 |
|
 |
So in my application where I am trying to load pStream into pPersistStream, the CLSID should be pPersistStream->GetClassID(&clsid). But i get the following error,
#define E_NOTIMPL _HRESULT_TYPEDEF_(0x80004001L)
CComPtr pPersistStream; Is IPersistStream the component that needs to be registered? If so how? Do I have to implement the function GetClassID somewhere?
|
|
|
|
 |
|
 |
Basically could you give me some insight on how to open regular files and load their streams into an IPersistStream.
|
|
|
|
 |
|
 |
Hi,
If your persistent component inherits from IPersistStream , then
the implementation of IPersist?s method (GetClassID) and IPersistStream? methods (load,save,GetSizeMax,IsDirty) are required. Because IPersistStream interface is derived from IPersist.You may choose a GUID for your class for example:
-----------------------------------------------------------------------------
// {49BF12F2-5041-48da-9B44-AA2FAA63AEFB}
const GUID CLSID_PersistComponent =
{ 0x49bf12f2, 0x5041, 0x48da, { 0x9b, 0x44, 0xaa, 0x2f, 0xaa, 0x63, 0xae, 0xfb } };
--------------------------------------------------------------------------
For persistants objects COM requires the component?s class id in order to associate it with persistent data and this can be achieved by implementation of the GetClassID method:
///////////////////////////////////////////////////////////
HRESULT YourPersistComponent::GetClassID(CLSID *pClassID) {
*pClassID = CLSID_PersistComponent;
return S_OK;
}
and for creation of an instance of your persistent component you can pass the component's clsid to the CoCreateInstance method:
CoCreateInstance(CLSID_PersistComponent,NULL,CLSCTX_ALL,IID_IPersistStream,(LPVOID*)&pPersistStream);
and it's also required that your component is registered in windows registrey if the client is going to use it via COM library.
|
|
|
|
 |
|
 |
Thank you so much for your reply...I will try the above out. Could you please give me more detailed steps on how to register the components in windows registry in code?
|
|
|
|
 |
|
 |
Hi,
If your COM server is a part of an application setup program, it will automatially be registered, otherwise an Inprocess COM server does the registereation/unregistereation by some entry points in the DLL with the following functions:
HRESULT DllRegisterServer(void);
HRESULT DllUnregisterServer(void);
i.e by implementaion of these functions a DLL would be able to register/unregister itself to/from the windows registery.
|
|
|
|
 |
|
 |
I had the following questions, and as I mentioned Im a really new to C++ so please be patient with me!
>the implementation of IPersist?s method (GetClassID) and IPersistStream? >methods (load,save,GetSizeMax,IsDirty) are required. Because IPersistStream >interface is derived from IPersist.
How do I implement these functions?
>You may choose a GUID for your class for example:
Which is the class in my case?
>and it's also required that your component is registered in windows registrey if the client is going to use it via COM library.
How is this done?
|
|
|
|
 |
|
 |
I had the following questions, and as I mentioned Im a really new to C++ so please be patient with me!
>the implementation of IPersist?s method (GetClassID) and IPersistStream? >methods (load,save,GetSizeMax,IsDirty) are required. Because IPersistStream >interface is derived from IPersist.
How do I implement these functions?
>You may choose a GUID for your class for example:
Which is the class in my case?
>and it's also required that your component is registered in windows registrey if the client is going to use it via COM library.
How is this done?
Thanks!
|
|
|
|
 |
|
|
 |
|
 |
I found another error in this project. The constructor of component2 trys to call Print, but Print relies on the inner object existsing which it doesnt yet do. In the constructor, m_pInnerInterface points to undefined, and attempting to call m_pInnerInterface->Print will of course kill the problem with a memory protection error. Commenting out the call to Print in the constructor of component2 fixes this error.
Great set of articles by the way. Extremely valuable learning material despite the one or two minor errors I have found. Your contributions are highly appreciated and I urge you to keep up the good work.
|
|
|
|
 |
|
 |
Hi,and thanks for your comment.
In the submitted code the consturctor of the component2 is as the following:
/////////////////////////////////////////////////////////////////////////////
CComponent2::CComponent2():m_cRef(1),m_pInnerInterface(NULL)
{
}
and I did not find the error you have mentioned, as you may view from the code first the class factory's CreateInstance(...) is called,
this method creates the outer component and in the constructor the pointer to the inner component(m_pInnerInterface) is nulled.
Then the outer component's CreateInnerComponent(...) is called. This method calls the CoCreateInstance(...) method,
passing the inner component's class id and it returns a pointer to the inner component(m_pInnerInterface),which will be used to call the inner component's methods.
|
|
|
|
 |
|
 |
Hello all,
From the article 'COM from scratch', it is neccessary to ship the header file (interface.h) to the users and the users must to include interface.h file into their code. So do you know how to avoid this case? If the user uses Matlab or VB for example, how do these program can understand the interface writeen in C.
Thanks in advance
|
|
|
|
 |
|
 |
Hi,
For using your component in VB or Matlab , your COM object should implement the IDispatch interface and by Implementing this interface the clients can get the necessary information about the methods and properties provided by the component.
For the example in this article ignoring the interface.h file requires the followings steps:
In the Server:
1- Define an odl/idl file : like component.idl
2- Define a type library in this file
-----------------------------------------------
import "oaidl.idl";
// Library
[uuid(9BDC8330-2D1A-458f-B92E-85B9B998F41D), version(1.0),
helpstring("Components type Library")]
library ComponentLib
{
importlib("stdole32.tlb");
[uuid(49BF12F1-5041-48da-9B44-AA2FAA63AEFB)]
coclass CComponent
{
[default] interface IComponent;
};
// IComponent definition
[object, uuid(853B4626-393A-44df-B13E-64CABE535DBF),
oleautomation, helpstring("Printing a Message")]
interface IComponent:IUnknown
{
void Print()=0;
};
};
---------------------------------------------
3- Compiling with the command( midl /env win32 /h "component_h.h" "component.idl") will generate these files :
Component_h.h
Component_i.c
Component.tlb
In the Client:
1-Include the files Component_h.h and Component_i.c in your client project
2-Ignore the ?interface.h? file
3-Run the Client
|
|
|
|
 |
|
 |
Hello all,
I would like to implement a function that return a vector of string.
In C++, it should be like this: vector Function();
Does anyone know how to write an IDL file for it.
|
|
|
|
 |