|
Hi Kev,
thanks for your fast reply! Well, the control is originally based on MFC, so I think this is worth a try.
Bye, Florian
|
|
|
|
|
Hi kev,
bad news so far. Overriding doesn't helps here. The function gets called, but generally returning TRUE hasn't had any effect. I changed it for crosschecking to FALSE and got a different error, when trying to invoke the function which returns the IDispatch reference to the internal object I want to expose.
But in general I'm right, when I suppose that JScript/VBScript should automatically generate a wrapper for a returned reference to an IDispatch interface ( IDispatch* in the used function) ? Or have I anything forgotten in that case ? My exposed Control doesn't implements these additional interfaces, but they're all defined and accessible in the corresponding typelibrary.
Bye,
Florian
|
|
|
|
|
Hi Florian,
I'm not too sure if I'm fully understanding your problem - it looked at first glance as if it was the same problem as mine.
To anyone else reading, if I put my foot in it, please correct me - in no way do I claim to be a COM wizard. Just been around the block a couple of times, learning as I go...
Basically, if you access a COM component or control using a scripting language, you're limited to whatever functionality is available on the default interface of the component which must be an IDispatch-based interface. Calls are made simply by the scripting host mapping the method or property name (string) onto an id (int) and passing this id along with parameter information to the IDispatch::Invoke method.
If your control implements only custom (IUnknown-based) interfaces, you won't be able to access its functionality from a scripting language.
If an MFC wizard was used, you'll almost certainly have at least part of your component exposed via a dual interface. If you've added any further secondary interfaces though, these won't be accessible to the scripting language.
Can you give me a bit more detail about your component - maybe attach an IDL file or even the coclass definition from the IDL file?
Kev
|
|
|
|
|
Hi Kev,
well, I suppose you're getting to the core there. All interfaces are implemented as dual, automation. It was a former MFC Control, which has been added ATL support. The control itself exposes their standard dispatch interfaces.
The basic definition is somehow like this:
[ object,
uuid(),
version(1.0),
dual,
oleautomation,
pointer_default(unique)
]
interface IMyIF: IDispatch
{
[id(0x00020001)] HRESULT fn1();
};
[ uuid(),
dispinterface _DCTL
{
properties:
methods:
[id(101),] [unique] IMyIF* GetMyIF();
[id(102), propget] IMyIF* ActiveMyIF();
};
[ uuid(),
control
]
coclass CTL
{
[default] dispinterface _DCTL;
[default, source] dispinterface _DCTLEvents;
};
All objects to be exposed are maintained internally in the control, an the
coclass definition of IMyIF is noncreatable. So all I do is, returning the IDispatch reference pointer to an existing instance within the control via the GetMyIF() function or property. The funny thing is, that I downloaded the ActiveX control pad from Microsoft today, which shows me the methods implemented by IMyIF when clicking the propget method ActiveMyIF, but it's not working either.
I suppose, somehow only access to the direct implemented Dispatch methods of the control is possible. But I think there must be some way, to generate objects based on the other exposed IDispatch references. At least, IDispatch should be working, because it's runtime callable. Weird,weird.
Thanks again for your suggestions,
Florian
|
|
|
|
|
JScript and also VBScript behaves really weird if you miss to tag out parameters properly in the IDL definition. Make sure they are [out, retval].
An eye for a tooth will only make you see weird things.
|
|
|
|
|
Hi Jörgen,
well, that 's maybe worth a try. Thanks for your suggestion !
Bye,
Florian
|
|
|
|
|
Hi, first time posting a thread here and it is out of desperation.
I am creating an ActiveX control using VC++ and i am trying to disallow the resizing of the control during design time (using the control in VB).
I spent 1 full day to draw an icon on the control and I am not going to spend another day trying to do this.
Is there any easier way? I know when creating a control, you can actually specify things like OLEMISC_ONLYICONIC. Anyone have a solution to this? Am i doing it the wrong way? Is there a checkbox I can tick somewhere which can do this?
Please help...
|
|
|
|
|
I am using the AxShockwaveFlashObjects.AxShockwaveFlash object on my C# winform. I have some swf files that require variables to be passed in using Flashvars. I can't use SetVariable because the swfs are not going to wait for me to set the variable. So, I would like to use the Flashvars property. However, it will not set. It doesn't complain if you try to set but it never takes. I have tried setting it during initialization but that does complain. Does anybody know how to set the Flashvars property? Please let me know.
David
|
|
|
|
|
Hello! Couldn't you please help me. I need to write IE toolbar on pure win32api and COM, but I'm not very experienced in this area: all toolbars that I've seen were written with use of ATL. What should I do for making IE toolbar without ATL? Thanks in advance.
Alexander.
|
|
|
|
|
You can do this but you will have to do all of the heavy lifting yourself to replicate the work that ATL does for you. You will have to write all of the code that registers your component with COM, etc. I suggessting using Google to look for examples of skeleton code for creating COM components without ATL.
Human beings were not meant to sit in little cubicles staring at computer screens all day, filling out useless forms and listening to eight different bosses drone on about about mission statements. -- Peter Gibbons
|
|
|
|
|
Hi,
I have an exe server and a client exe, the server starts up and does a CoRegisterClassObject for an IClassFactory implementation that provides "ComTestObject" instances.
The Client does " CoCreateInstance", while debugging the server I can see that the object requested ("IComTestObject") is created in the Class Factory and the pointer from the client is set. The IClassFactory returns S_OK
Now, I jump back to debugging the client, and CoCreateInstance returns 0x80004002 = "No such interface supported"
I really don't understand why this is being returned. When I clearly saw the server code create a new ComTestObject and return S_OK
What am I doing wrong, is there some common mistake here?
Here is the code for the Factory CreateInstance method, in the server:
/*--------------*/
STDMETHODIMP ComTestObjectFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv){
ComTestObject *p_obj;
HRESULT hr;
if (pUnkOuter)
return (CLASS_E_NOAGGREGATION);
if (IsEqualIID (riid, IID_IUnknown) ||
IsEqualIID (riid, IID_IComTestObject)) {
// Create New menu item object.
p_obj = new ComTestObject();
if (!p_obj)
return E_OUTOFMEMORY;
// See if object exports the proper interface.
hr = p_obj->QueryInterface (riid, ppv);
// This will cause an object delete unless interface found.
p_obj->Release ();
return hr;
}
return E_NOINTERFACE;
}
/*--------------*/
Here is the client code that asks for the object:
void makeObject(){
CoInitialize(NULL);
ComTestObject *p_obj;
HRESULT res=CoCreateInstance(CLSID_ComTestObject,NULL,
CLSCTX_LOCAL_SERVER,IID_IComTestObject,(void**)&p_obj);
}
Thanks for any help with this.
- Tom
|
|
|
|
|
Hi,
Actually i am writing application automating MS Excel 2003.
I need a complete description of arguments type passed to the MS Excel COM interface.
For example CFont0::put_FontStyle(VARIANT NewValue)
How do i know the 'NewValue argument' type ?
I don't find on the web any website that explains that.
KXY
|
|
|
|
|
Variants in COM can be almost anything (you probably know that, right?).
There are help files that describe the Office object type library hierarchy, written for Visual Basic programmers that are extremely well hidden on your computer. Try the OLE/COM Object viewer to locate them.
You don't say which language you are writing this application in, or, whether it's a .NET application or something else. This information is important in determining your approach to the problem.
If you are writing a .NET app, try using the TlbImp.exe utility included with the Framework SDK to convert the COM type library into a .NET assembly (this you can then examine with the IL Dissassembler to determibe types.
|
|
|
|
|
Let me know what u want to automate using Excel?
e.veera raghavendra
|
|
|
|
|
I've been battling around trying to implement WMI into my MFC application. I'm trying to get Windows XP informations such as product key, activation status, ect. I used COM init to interface with Win32_WindowsProductActivation class. I have problems with changing Windows XP Product Key. How can I run SetProductKey method with parameters??? I went through Microsoft docs but it's not clear to me at all. Any hits or sample code??? I've seen VB script but i have difficulty implementing it with C++.
Thank you all
|
|
|
|
|
problem in registering WMI Provider dll
I have 32bit WMI Provider dll,i can register(by regsvr32) this dll in .net installed system.but i could not register this dll without .net full installation(but i installed .net framework).Is there anyother configuration needed for registering this dll in without .net full installion
senthil
|
|
|
|
|
Hi there,
while taking some first steps in programming COM interfaces, I'm stuck at some point. Here's my question:
I'm trying to add COM functionality to an existing application. Tnis application contains already a MFC Dispatch interface. My new COM interface tried to prevent in the first step using IDispatch, to have some more possibilities defining interfaces and datatypes. What I did is following:
1.) Extended the existing Dispatch interface with a function, which returns an IUnknown**, which exposes the interface to an internally created and maintained object.
2.) Created a custom interface, derived from IUnknown, which can' t be directly created and is basically used as proxy object.
Extended dispatch interface, returns pointer to existing instace of my object:
<br />
[id(100))] SCODE GetObjRef_ppUnk([out] IUnknown**);<br />
Interface definition to be returned:
<br />
interface IMyInterface : IUnknown<br />
{<br />
import "unknwn.idl";<br />
<br />
HRESULT my_proc([out] myparam* p);<br />
}<br />
Working CPP code calling the OCX Control:
<br />
#import "libid: ... my GUID ... " <br />
<br />
LPUNKNOWN pUnk = NULL;<br />
BOOL bOK = FALSE;<br />
MyLib::IMyInterfacePtr pMyIF;<br />
int iRet = 0;<br />
MyLib::myparam myParam = {0}; <br />
<br />
bOK = m_myCTL.GetObjRef_ppUnk(&pUnk);<br />
pUnk->QueryInterface(IID_IFMYIF, (LPVOID*)&pMyIF);<br />
if(pMyIF)<br />
{<br />
<br />
pMyIF->my_proc(&myParam);<br />
<br />
} <br />
The object instance to be exposed via the interface is completely handled internally in the OCX control. Therefore, my custom interface is declared as noncreatable.
While this is working as expected in CPP , I don't get it running with VB, MCPP, C# , which I'm also not very familiar with at the moment. I tried somthing like this (Managed C++):
<br />
System::Object *pUnk = NULL;<br />
Interop::MyLib::IMyIF * pMyIF = NULL; <br />
Interop::MyLib::MYPARAM myParam = {0};<br />
<br />
<br />
this->axMyCTL->GetObjRef_ppUnk(&pUnk);<br />
<br />
if(pMyIF)<br />
{ <br />
pMyIF->my_proc(&my_param);<br />
}<br />
Similar code also doesn't works in VB/C#. I suppose, it has to do with the managed thing. When calling GetObjRef I get an "An unhandled exception of type 'System.ExecutionEngineException' occurred in mscorlib.dll" . I there a legal way to accomplish this, or do I have to use the IDispatch interaces ? I searched a lot and have also the Nathan Book ".NET and COM Interoperability Guide", but I didn't found any suitable solution for my problem. The strange thing is, that the IUnknown** isn't diplayed as such in the Interop Classwrapper, but as some __MIDL_0010 type. I thought, IUnknown** can be legally used on dispatch interfaces, because its also contained in the VARIANT struct...
The basic question would be, as what kind of object the IUnknown** is handled by the underling marshaling code (if it is marshaled..).
Any helpful suggestions are very appreciated. Thanks in advance , if you read this sermon 'til this line...
Bye,
Florian
|
|
|
|
|
Probably a dumb answer as well, since I'm not an expert in COM...
But all COM made in VB that I've seen has IDispatch interface, so I guess that VB might not know how to deal with the IUnknown. What I don't understand, if you have IDispatch already, why do you want to use IUnknown ? Found IDispatch is much easier to use, and though I'm not sure how VB deal with IUnknown, it's certainly can deal with IDispatch.
Good luck...
|
|
|
|
|
Hi hanofee,
hanofee wrote:
What I don't understand, if you have IDispatch already, why do you want to use IUnknown ? Found IDispatch is much easier to use, and though I'm not sure how VB deal with IUnknown, it's certainly can deal with IDispatch.
basically it's because the object I want to expose is allocated and maintained in the main ActiveX Control itself. So I need a way to expose the interface of this instance, and at the current point, it's the only working way. Maybe someone has some example code showing how to cast an IMyInterface** of an object inside an ActiveX control exposed via IDispatch to an object in VB/C# or whatever... I still didn't got it working. Maybe also something is wrong on the server side...
Florian
|
|
|
|
|
Meanwhile I switched to ATL, which seems to solve some of the problems. Main problem was obviously in the server, that I casted the reference to be returned via a static_cast to the IUnkown/IDispatch Base interface. This seemed to cause some hassle, when using other languages than C++. I now return a reference, which is initialized via the QueryInterface process for the IDispatch interface. No everythings working fine.
|
|
|
|
|
Question 1:
I have:
1. exe COM client A.
2. exe outofproc COM server B which is also a client to:
3. dll inproc COM server C.
So B creates an instance of C. And passes the pointer to it to A. Can A actualy call C which is in B process space?
Question 2:
I have:
1. A is an exe COM client .
2. B is an exe outofproc COM server.
When A releases all instances of B, B unloads. Good! That's what I need. BUT! If:
2. B is a dll inproc COM server.
Then When A releases all instances of B, dll B still is loaded by A process for a while.
Is there a way to force it to unload?
Thanks a lot!
|
|
|
|
|
inner wrote:
Question 1:
I have:
1. exe COM client A.
2. exe outofproc COM server B which is also a client to:
3. dll inproc COM server C.
So B creates an instance of C. And passes the pointer to it to A. Can A actualy call C which is in B process space?
No. Although there is nothing to prevent you from writing this sort of code, the pointer that A receives to C is invalid. You can only call a function in a DLL loaded in an executables own process space.
inner wrote:
Question 2:
I have:
1. A is an exe COM client .
2. B is an exe outofproc COM server.
When A releases all instances of B, B unloads. Good! That's what I need. BUT! If:
2. B is a dll inproc COM server.
Then When A releases all instances of B, dll B still is loaded by A process for a while.
Is there a way to force it to unload?
This is a more complicated question. The actual reference counting for a DLL can become more complex than what you think it should be because COM may create references behind the scenes to additional interfaces such as proxies.
It also depends to at least some degree on the platform you are using to create the COM objects (i.e. VB is a little different from C++).
If you are using C++ a call to CoFreeUnusedLibraries() should unload the DLL.
If you are using VB, most of the COM implementation is hidden from you, and the safest thing to do is just allow the runtime to clean up after itself.
Robert
|
|
|
|
|
Thanks a lot! I'll try the CoFreeUnusedLibraries()
And I would agree with you on the access violation (question 1), but I have a programmer that sitts right across from me and he just wrote that code and it worked. I didn't try that. He says that through the A->B->C is about 3 times slower than direct A->C (when A create C on it's own). I refused to beleave but don't have time to verify that so I asked here.
|
|
|
|
|
OK, without seeing the code, it is hard to know exactly what he is doing.
Trying to copy a pointer into another process by simply moving the rvalue will result in an invalid call, because the rvalue is an address in another process.
If it works what he is doing is marshalling the pointer into process A. This is a valid COM operation. What happens when you marshall a pointer between two processes is COM is creating a proxy behind the scenes in A that allows A to call B and request a function call on C. The reason this is slower is because A is still not calling the C DLL directly (this is not possible under any circumstances). Instead it is calling a proxy that forwards the request to B, which then forwards the request to C on behalf of A. The behind the scenes proxy call from A to B is out-of-process, so it runs more slowly than a in-process DLL function call.
There are scenarios when an "A->B->C" style call arrangement is appropriate - usually if the C DLL maintains any state that both A and B either require access to, or that must be maintained by C across both A nd B function calls - i.e. A calls a function in C that results in setting some state variables. B then calls another function in C that also depends upon the state set by the previous function call from A).
In this case you would design your DLL to be loaded by whichever process - A or B - is anticipated to make the most calls to the DLL to minimize the performance hit.
If the rationale for an "A->B->C" style call is not based on a shared state requirement, then the performance hit is probably not worth it. For exampole, suppose you want to load only one instance of C to reduce memory consumption. When A and B are created they run on separate threads, each of which is allocated a pretty big chunk of memory at startup. Calling C from A via B is probably causing a pointless performance hit because A may not be using memory it already has allocated. Unless your C DLL is really huge, you might as well load the C DLL in both processes and eliminate the proxy.
Robert
|
|
|
|
|
Quick links for your question
Ans 1. Check Aggregation and Conatainment topics/features in COM
Ans 2. Check CoFreeUnusedLibrary API and DllCanUnloadNow wellknown exported function from INPROCSERVERS
Have a great day ahead!
Regards,
Sohail Kadiwala
(My Blog - http://blogs.wdevs.com/sohail/[^])
modified 21-Apr-21 21:01pm.
|
|
|
|
|