|
Thanks for offering to take a look at it. Rather than posting all the code here I've put it into a zip on my site to download.
test.zip
The zip contains 2 zip files. One is the test client and the other the servicefactory. I'm using VC6 and WTL7 (I'm in love with CString!).
ServiceFactory has a method GetService(BSTR name, IPObject**ppObj) which will get either the FoodService or the BeverageService depending on the string passed in. PObject has a virtual method ExecuteServie(BSTR param) which calls a virtual method Display. ExecuteService is only implemented in PObject. Display is only implemented in the subclasses.
If you step through the test client you can actually see that the right object is created however when I called ExecuteService it throws an unhandled exception.
Thanks again!
ed
|
|
|
|
|
Ed -
The problem is you are trying to call a ExecuteService using a IFoodService pointer. This would work if IFoodService were derived from IPObject, but it is not ! This means that the vtable entry for ExecuteService just does not exist for IFoodService. Typecasting it via reinterpret_cast wont fix it either.
I made the following change and it worked for me.
In File factory.cpp
Note that we now QI for IPObject instead of IFoodService
<br />
return CComCreator< CComObject<CBeverageService> >::CreateInstance(NULL, IID_IPObject, reinterpret_cast<void**>(ppPObj) );<br />
This would ensure that the interface pointer for IPObject is returned instead of IFoodService. If you really want IFoodService on the client, you can always QI for it from IPObject.
Suggested change
Change the interface map for CFood and CBev
<br />
BEGIN_COM_MAP(CFoodService)<br />
COM_INTERFACE_ENTRY(IFoodService)<br />
COM_INTERFACE_ENTRY_CHAIN(CPObject)<br />
END_COM_MAP()<br />
This is because CFoodService does not directly implement IPObject but rather uses the implementation already defined in a base class. The QI then searches for the implementation in the base class.
Hope that helps-
Vivek
|
|
|
|
|
What it comes down to is that I have to implement ExecuteService in each of the base classes to handle the initial request (Command Pattern) then let it call a template method in the parent class to get things moving as I want them to. I really don't want the client to have a clue as to what he is calling. That way I can add other base classes without having to recompile the client.
Thanks for checking it out. I really appreciate it!
ed
The nice thing about egotists is that they don't talk about other people.
Lucille Harper
|
|
|
|
|
Hi everyone,
I am not able to find a way how to use the only one (common) instance of my COM object from several processes. Here I see the only solution of multiple instances and that way I lose some of the pointers.
Can anybody guide me how to do that?
Thanks,
Jawid
|
|
|
|
|
Have you tried using RegisterActiveObject, to put your object in the ROT? Then you can use GetActiveObject.
Scot Brennecke
Software Developer
VC++ MVP
|
|
|
|
|
I found that macro :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/vcoriATLMacrosAlphabeticalReference.asp
The particular one is :
DECLARE_CLASSFACTORY_SINGLETON
Hope this helps.
|
|
|
|
|
If you com object was developed using ATL then there is a macro you can use to make it a singleton, meaning only one instance of it will be created and shared between all clients. Im sorry but i can't remeber what the macro is, its something like ATL_DECLARE_SINGLETON. Have a poke around in the MSDN although i found it in one of the wrox atl books.
|
|
|
|
|
Hi,
I’m sorry but I did not fully understand your question? You want to use the some instance of a COM object in different processes or different threads in the same process?
If you want to pass a pointer to a object to another thread in a running process you have to be aware of the COM Threading Model (Apartments) and Marshalling see http://www.codeguru.com/activex/COMApartments1.html and http://www.codeguru.com/activex/COMApartments2.html .
.
If you really want different processes to access the same COM object, then this last has to be implemented in a out-process (.exe) COM server having the class factory returning the same object every time a instance of that class is requested. Remember that using an out-process com server you’ll be linking whit a proxy/stub dll (Marshalling).
http://www.codeguru.com/activex/MiniDcom.html
I recommend you reading Essential COM (Don Box), ATL Internals (Brent Rector) and Learning DCOM (Thuan L. Thai)
|
|
|
|
|
Hi Guys,
Thanks for great help. All of those advices seem very helpfull. I tried the solution with macro for singleton object and it works nice.
Thanks,
|
|
|
|
|
Make sure that it is an exe service rather than a dll service. A dll singleton loads a different instance per app. An exe will have only one instance.
ed
The nice thing about egotists is that they don't talk about other people.
Lucille Harper
|
|
|
|
|
Ok. I'm trying to use a COM OCX object in a C program. I've done some research and found out how to call and instantiate a COM object from C. However, I do not know how to generate a header file for object type or interface declarations.
SOPTEST replied with some useful info but all I can find out is info on how to develop a COM object using C and not how to use an existing one that is already in the registry that I didn't develop. I want to use MSCOMM32.OCX in a C program. How do I get the declaration for the IMSComm and other interfaces?
I know how to get the IUknown interface, call QueryInterface, etc. And, I know that getting an interface pointer is really a void** so I could create a void pointer and call it anything I like and use it but that doesn't seem right or is it???? I've learned how to view the typelib, CLASSID, etc. from OLE/COM Object viewer so I don't think I'm an idiot, I just need some help.
Is there someway of interpreting the type library and converting it into a header file that I am not aware of? Anybody??
|
|
|
|
|
Use "oleview" to open type library. From "File" menu you can "Save as" *.IDL, *.H or *.C file. If you save it as *.IDL file then compile it with MIDL compiler to generate proxy/stub files.
soptest
|
|
|
|
|
I used "oleview". I did not know you could save .c or .h files from there but when I tried, it didn't work. Apparently, it uses a console window but the error happens so fast and the console window closes before I can see it. However, I was able to save the .idl file. But, going from using VC++ before with Add To Project | Components and Controls that generates all C++ wrapper classes and as you say proxy/stub files for out of process.
|
|
|
|
|
I think I got it now. I was finally able to save a .c and .h files to the default directory (system32). I still got warnings or errors but I couldn't tell what they were. Looking at the contents it has the proper extern "C" declarations Cool!
Thanks again, SOPTEST
|
|
|
|
|
If you're using MSVC++ (and what else would you be using !!), you can use '#import ' to import COM objects. This will generate the required header files automatically when you compile the code. The one pain is that (with VC6, but not VC.NET, IIRC) you need to enter an absolute path to the DLL or OCX or whatever. (I've just looked it up - VC++NET lets you use a progid to say what class you want). MSDN (the one you get with VC++) should hopefully have enough info to get you started.
Just one thing - by default, VC++ will generate wrappers for the COM class - this may not be what you want.
Stuart Dootson
'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'
|
|
|
|
|
Whoops - just read your message properly - you say you're using C, as opposed to C++, so this may have been of no use whatsoever
Stuart Dootson
'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'
|
|
|
|
|
OK - not really a problem, but is there anything supremely wrong with this:
I've got some COM objects I'm using as helpers to get a scripting application (using IActiveScript with a user-selectable script engine) working (specifically, I've got an IActiveScriptSite implementation and some IDispatch-based objects that I'm inserting into the scripting namespace with IActiveScript::AddNamedItem). BUT...these objects are not registered COM classes, because they're just classes in a standard Win32 executable, not a COM server executable - I create them using 'new CComObject<class name> ' and manage them with _com_ptr_t..or is it CComPtr - can't remember which right now. It all seems to work - but is there any reason that I should be using properly registered servers & objects & things?
Stuart Dootson
'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'
|
|
|
|
|
Nope. If you're not going to use the objects outside the scope of your application, there's no reason to register them.
Scot Brennecke
Software Developer
VC++ MVP
|
|
|
|
|
I'm trying to utilize Microsoft's MS XML 4.0 parser to obtain some data from an XML file. I'm using C++ so im I'm having a bit of trouble writing a simple console app that can find an XML node of my choice and retrieve data associated with it. I am trying to utilize the XML DOM Method GetAttribute.
(as seen on MSDN @ http://msdn.microsoft.com/library/en-us/xmlsdk/htm/xml_mth_dg_5rfo.asp
I've worked through another example tutorial which creates a very simple app that loads the whole XML document and prints it to screen. I have no trouble with that but when I tried to utilize the MSDN example for GetAttribute, the code is riddled with problems and I have been unable to over come them. I'm sure if i saw a simple app that did what i was looking for i would understand how to use this better, but i have looked all over for such an animal and they are either way too big or way to simple to get anything from them. I am also having some troubles fully understanding _variant_t and _bstr_t.
If anyone can provide some advice or a very simple example (like something that can read 10 line xml file and find one tag in it and print its data), I would be grateful.
PS:
My problem may stem from: GetAttribute code: MSDN says it takes two parameters but it will not compile that way. SetAttribute appears to take similar parameters and it will compile with 2 parameters.
Thanks
Jeff Rothenberg
Project Engineer
Vector CANtech, Inc.
|
|
|
|
|
I've followed the tutorial about creating office addin's. The one I've created is an excel addin. It doesn't do anything, it's just a minimal addin.
But it doesn't show up in the excel addin-list, even though it's registered in windows registry.
The loadbehaviour should be set to 3 for automatic loading.
After compiling the project, using regedit shows 3 for loadbehaviour. So far so good.
But after running excel, eyeballing the addin is not there, the loadbehaviour in regedit changed to 2 ??????
What's going on here?
[VISUAL STUDIO 6.0] [MFC] [WIN98/2]
Bluute tette!
|
|
|
|
|
Hi,
as far as Excel addin is concerned, there are a few caveats as I have found out. If you have followed my tutorial and have a bare bones COM dll ready, to properly register it here's some info:
1) the registration key is to be created as usual at HKCU(or HKLM)->Software->Microsoft->Office->Excel->Addins->[Your Addins ProgID]. Now under this, apart from the usual FriendlyName,LoadBehavior and Description, you have to add 2 more entries. These are :
FileLocation - a string value of the physical path where the dll is located.
CommandLineSafe - a DWORD value(0 - unsafe 1-safe)
thus for my ATL Excel2000 addin project, the additions to the registry script(.rgs) are:
HKCU
{
Software
{
Microsoft
{
Office
{
Excel
{
Addins
{
'XLAddin.Addin'
{
val FriendlyName = s 'Excel2000 Addin'
val Description = s 'ATL COM Excel Addin'
val LoadBehavior = d '00000003'
val CommandLineSafe = d '00000001'
val FileLocation = s '%MODULE%'
}
}
}
}
}
}
}
with this, my addin gets loaded at startup.now as to the weird registry value changes, if the CommandLineSafe is 0,(i.e. addin is not safe to load) or the entry is missing ,Excel increments or decrements the LoadBehavior value, as some kind of a precaution.
happy addin programming.
'My capacity for happiness', he added, 'you could fit into a matchbox without taking out the matches first'.
- Marvin, the robot.
Amit Dey
sonork: 100:18407
msn: visualcdev
|
|
|
|
|
ok tnx
will try it...
[VISUAL STUDIO 6.0] [MFC] [WIN98/2]
Bluute tette!
|
|
|
|
|
do you know in a method call how to get the caller thread id if the interface has been marshalled ?
the problem is if the interface has been marshalled the GetCurrentThreadID return obvously the ID of the marshalled thread on which the interface has been marshalled. But how to get the thread id
of the calling thread ?
thanks in advance
|
|
|
|
|
why do you need to know it?
Len Holgate
www.jetbyte.com
The right code, right now.
|
|
|
|
|
Len,
it's funny you answer with a question
anyway it's a bit complicated to explain in few words.
I've used the IMessageFilter and it's not perfect but it works (only in STA)
ciao
|
|
|
|