|
In case of COM inproc server (DLL):
#import "c:\tmp\testobj\debug\testobj.dll"
typedef DWORD (WINAPI _DllGetClassObject)(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
int main(int argc, char* argv[])
{
::CoInitialize(0);
{
HINSTANCE hi = ::CoLoadLibrary(L"c:\\tmp\\testobj\\debug\\testobj.dll", TRUE);
HRESULT hr;
_DllGetClassObject *f;
f = (_DllGetClassObject*)::GetProcAddress(hi, "DllGetClassObject");
hr = ::GetLastError();
//CLSID of you COM object CLSID_test
CLSID clsid = {0xC795331E,0x0C56,0x11D6,0xA0,0xFD,0x00,0xB0,0xD0,0xC3,0xD9,0xBD};
::IClassFactory *pcf;
::TESTOBJLib::Itest *pObj;
hr = f(clsid,IID_IClassFactory,(void**)&pcf);
if(SUCCEEDED(hr))
{
hr = pcf->CreateInstance(0,__uuidof(::TESTOBJLib::Itest), (void**)&pObj);
pcf->Release();
if(SUCCEEDED(hr))
{
hr = pObj->In("test");
pObj->Release();
}
}
}
::CoUninitialize();
return 0;
}
soptest
|
|
|
|
|
I need to pass a menu from one COM object to another. Is this possible? The menu would be an out parameter, do I need to allocate memory for this? Or can I just pass a HMenu and duplicate (DuplicateHandle (???)) this on the other side?
|
|
|
|
|
idl definition:
[id(11), helpstring("method GetMenu")] HRESULT GetMenu([out] HMENU* pmh);
C++ implementation:
STDMETHODIMP Ctest::GetMenu(HMENU *pmh)
{
if(!pmh) return E_POINTER;
*pmh = m_hMenu;
return S_OK;
}
soptest
|
|
|
|
|
Thanx for answering. But when you pass something as out parameter, the caller is responsible for freeing the allocated memory, so mustn't the server copy the HMENU? If so, how do you do this? There does not seem to be a method for copying HMENU's.
|
|
|
|
|
HMENU is DWORD, so
in application:
HMENU rhm = 0;
pObj->GetMenu(&rhm);
if(rhm)
{
//rhm now has value
}
soptest
|
|
|
|
|
Hi All,
I was trying to write a connection point console client using c++ and ATL.
Can any body give me some pointers in this. I dont want to use MFC.
Thanks in Advance
Anil.S
|
|
|
|
|
I'm accustomed to using COM in one of two ways:
- As a client when I need to call into an interface for a given method to perform a specific task
- As a component that performs a finite task
However, with the COM+ Loosely Coupled Events I'm confused about how a particular scenario would play out. Let's say I have a CodeProject like application where I want certain subsystems to be alerted any time a new article has been added to the system. Therefore, ...
- I create an ATL project (NewArticle) and add an ATL component to it with an interface called INewArticleEvent and a method called NewArticle.
- I create a new COM+ application (NewArticleApp) and add the INewArticleEvent component as an event class.
- I create another ATL project (LatestUpates) and add an ATL component to it and implement the INewArticleEvent interface.
- For this second component, I create a new COM+ application (LatestUpdatesApp) and add the component as a regular class (as opposed to an event class).
- I add a subscription to the component and specify the INewArticle.NewArticle interface.
- Now when I write code to fire the NewArticle event, the subscribing component in my LatestUpdates component is called as it should be by COM+.
So, it's all good, right? However, here's my question. What if I want to update a currently GUI as a result of an event having been fired? I have this LatestUpdates component that's getting called. But, how can I somehow tie that to my MFC application so that I now list the new article on it's form view?
I'm sure this is COM+ 101, but I'm at a loss.
Thanks for anyone that can help me!!!
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
Your object that implements the INewArticleEvent interface can be any type of object that you want, as long as it implements that interface. Simply triger the UI update functionality that you would like to happen in your implementation of the INewArticleEvent interface. You can have more than one implementation of this interface. The event sink will blindly call the interface function that you give it.
There are two very good articles in MSDN about event sinks:
Dr. GUI and COM Events PArt 1
Dr. GUI and COM Events PArt 2
Good Luck
Build a man a fire, and he will be warm for a day Light a man on fire, and he will be warm for the rest of his life!
|
|
|
|
|
I'll definitely have to check out the articles because when I create an MFC app and add an ATL object to it (in order to implement INewArticleEvent) COM+ won't allow me to make it a subscriber - maybe EXEs can't contain subscribers (?)
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
Tom, check this article
COM+ Events hands on
Exes can contain subscribers, subscribers should be implemented in dlls and added to COM+ component services snap-in in your COM+ application.
And since you like books, I strongly advise you to buy "COM and .NET Component Services " by Juval Lowy at amazon BEST book on COM+ ever!!!!
And Tom , do yourself a nice thing ... go to sleep
Cheers,
Joao Vaz
Frustrated TCL programmer,good c++ programmer wannabe
|
|
|
|
|
Hi Joao!
Actually, Jeff's article is too simplistic. He's doing the standard old "display a message box when your method gets called from COM+" bit that I (and many others) have already done in books and articles past. I need a more practical application where the subscriber is part of a gui app that updates a real application. For example, let's say that I have an MFC SDI app with a listview listing auto parts. When a new part gets added to the system, I want my listview to be notified and be updated accordingly. This is the sort of thing nobody does in their articles or chapters.
Joao Vaz wrote:
Exes can contain subscribers, subscribers should be implemented in dlls and added to COM+ component services snap-in in your COM+ application.
Ok. It's early so bear with me You just said that exe can contain subscribers, but then you immediately reversed that and said that they must be in dlls In my tests, I have not been able to create an MFC app and add an ATL object that will implement my event class, COM+ won't allow me to define a application using that component's tlb as a subscription component.
Joao Vaz wrote:
And since you like books, I strongly advise you to buy "COM and .NET Component Services " by Juval Lowy at amazon BEST book on COM+ ever!!!!
Actually, I know Juval very well and he's definitely bright. I'll have to check his book out. However, I'm a bit under the gun now and need a more immediate resolution.
Joao Vaz wrote:
And Tom , do yourself a nice thing ... go to sleep
If only ....
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
Okay, I will try to explain better ...
quoting Juval:
For COM+ to implement an event class for you, you have to provide COM+ with the sink interfaces definitions, the event class CLSID, and the interface each event class supports. You provide this information in the form of a type library. The type library has to be embedded as a resource in a DLL. The Component Install Wizard knows how to read the type library from the DLL and detect the CoClass definitions inside.
For every CoClass in the type library, COM+ tries to generate an event class and add it to your application as a component. COM+ synthesizes implementation only to interfaces that are part of the event class CoClass definition in the type library.
For example, to define the event class MyEventClass that supports the sink interface IMySink (shown earlier), your IDL file should look like this:
[
uuid(0A9B9E44-E456-4153-9FC8-5D72234B7C82),
version(1.0),
helpstring("Event Class 1.0 Type Library")
]
library EVENTCLASSLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
importlib("SubApp.tlb");//The subscribers' TLB
[
uuid(5CAF8E95-3FEF-40F1-94C3-3F408240D53B),
helpstring("MyEventClass Class")
]
coclass MyEventClass
{
interface IMySink;
};
};
To avoid repeating the definition of the sink interfaces in both the subscriber application and the event class type library, the event class IDL file should import the sink interface (IMySink) definitions from the type library of the subscribers. This is what the line importlib("SubApp.tlb");was used for in the previous example.
end of quotation ...
You should only put your event class in the dll, do not mix with other coclasses ... because this surely will confuse the com+ install wizard, also you should provide your registration logic, this can be achieve inserting a dummy atl object and assert the methods,because this methods aren't never to be called in the first place.
For instance and taken from Juval book
class CMyEventClass :
public CComObjectRootEx<CComMultiThreadModel> ,
public CComCoClass<CMyEventClass,&CLSID_MyEventClass> ,
public IMySinkInterfaceThatYouWantToImplement
{
public:
CMyEventClass( ){};
DECLARE_REGISTRY_RESOURCEID(IDR_MYEVENTCLASS)
DECLARE_PROTECT_FINAL_CONSTRUCT( )
BEGIN_COM_MAP(CMyEventClass)
COM_INTERFACE_ENTRY(IMySinkInterfaceThatYouWantToImplement)
END_COM_MAP( )
// IMySink
public:
STDMETHOD(OnEvent1)( ){ATLASSERT(0);return E_NOTIMPL;};
STDMETHOD(OnEvent2)( ){ATLASSERT(0);return E_NOTIMPL;};
};
The interface could be a custom or automation and should only have [in] parameters, forget the [in] and [in,out] ...
Hope this clears a tiny bit ????
Cheers,
Joao Vaz
Frustrated TCL programmer,good c++ programmer wannabe
|
|
|
|
|
Tom, I forgot to mention , that probably you only can achieve what you want with Transient Subscription model ?(not sure), this can be programmed using only the COM+ Catalog Api , this model is designed for apps that are already running, in opposite way you have the Persistent Subscription model, that can be added with COM+ snap-in .
To add a transient subscription , you must follow these steps:
Create the catalog object (CLSID_COMAdminCatalog) and get a pointer to ICOMAdminCatalog.
Call ICOMAdminCatalog::GetCollection( ) to retrieve a collection called TransientSubscription and get back an ICatalogCollection interface pointer.
Call ICatalogCollection::Add( ) to get ICatalogObject.
Call ICatalogObject::put_Value( ) once for each desired property of the transient subscription you want to set. Some examples are the event class you want to subscribe to, subscribing interfaces, and the subscription name. An important property you need to set is whether or not you want to enable the subscription.
Call ICatalogCollection::SaveChanges( ).
Release everything.
(The steps are coorect, I think is still from Juval book)
To have to do a similiar thing to unregister the subscription when you application ends (if ends after all)
Cheers,
Joao Vaz
Frustrated TCL programmer,good c++ programmer wannabe
|
|
|
|
|
I truly appreciate the long posts and attempt to help. However, all of this I have down pat and have done dozens of times. What I haven't done is to have a subcription component communicate with an GUI application once it gets the event notification with what I'd call an elegant means. For example, I typically post a message to the application from the component. However, what I'm wanting to know is if an MFC applciation can also have defined an ATL component that is itself the subscriber to a COM+ event. That way, I can simply call AfxGetApp from the component and commnicate with my app that way. Sorry if I'm not explaining this well as I'm under the gun for a deadline and going back and forth between this and the code.
Thanks again though for your help!!
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
Yes , you can have a MFC app that have a ATL object that's itself part of the subscriber to a COM+ event.
I think that i'm already did this using the posts above with a mfc app, but that was in january , and I don't remember the details
But yesterday night I found that O'reilly have the book online and the examples from the Juval book, if i'm not mistaken , there is a sample using MFC and ATL to do this kind of thing that you want to do.
Sample code of the COM and .NET book
I post here the link, because the book have some very good points about subscriptions and other COM+ juicy stuff
Read the COM and .NET online
I hope you don't get shoot
Cheers,
Joao Vaz
Frustrated TCL programmer,good c++ programmer wannabe
|
|
|
|
|
By the way, thanks for the help! Sorry. I'm not awake yet.
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
i am a new of com,can you give me some advice
@viruslee@
|
|
|
|
|
Purchase a book called COM Programming by Example and dive in!
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
|
Get a copy of Essential COM if you really want to understand it.
I'd also look into ATL as it makes COM programming a lot easier. The Wrox Press ATL books are very good.
Michael
Communication is the first step towards enlightenment.
|
|
|
|
|
How can i make an IPC with my own COM component? Which type of COM server (.dll or .exe) and threading model must i use?
|
|
|
|
|
If you use ATL all of that stuff is taken care of for you. You can use any threading model that you would like, and any type of COM server. I am think that MFC will handle the marshalling for you as well, but I am not positive.
If you do not use one of these tools, then you will have to create your own mechanism to communicate to the other process, whether it is Memory mapped files, TCP/IP or some other method.
Build a man a fire, and he will be warm for a day Light a man on fire, and he will be warm for the rest of his life!
|
|
|
|
|
While trying to build a ActiveX control using ATL (with MFC support) & i run into these linker error messages & the funny thing is I'm not using/referencing RichEdit control at all!
uuid.lib(cguid_i.obj) : error LNK2005: _IID_IRichEditOleCallback already defined in OrderEntryCtrl.o
uuid.lib(cguid_i.obj) : error LNK2005: _IID_IRichEditOle already defined in OrderEntryCtrl.o
Any clues?? TIA
Chen Venkataraman
|
|
|
|
|
I should add that the ActiveX control is subclassing a Edit control
Chen Venkataraman
|
|
|
|
|
Never mind - i figured out
I was using the ATLControls.h (from the MS sample atlcon) that provides wrapper methods for all the common controls.
This file also includes additional header files
#include "richedit.h"
#include "richole.h"
that relate to RichEditCtrl & i suspect these were causing the problem.
For now, i excluded them in my project by defining _ATL_NO_RICHEDIT in my project & modifying the ATLControls.h header to conditionally include them like so.
#ifndef _ATL_NO_RICHEDIT
#endif
Chen Venkataraman
|
|
|
|
|