|
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.
|
|
|
|
|
Hi,
I'm trying to write an Out of proc DCOM server in C#. I have the Server written, its now a COM object so thats done.
Where i'm stuck is this. As far as I kmow, DCOM works by having a stub object on the machine that the server is running on, and then a proxy on each of the client machines that communicates with the stub object.
How are the stub and proxy objects created? I'm told that in C++, they are created automatically but I am developing this in C# so I need to know if it works the same. The client is written in C++ and the DCOM server is written in C#.
Any help or comments will be appreciated
Thanks
Millzy
|
|
|
|
|
Hi all!
I have a COM DLL (Project1) which defines an enum, along with interfaces that uses it.
I have a 2nd COM DLL (Project2) which also needs to use this enum in its interfaces.
I've split the enum out into a separate .IDL file, and then tried various combinations of importing or #including this into both main IDL files. I've eventually managed to get them both to build, but then when I try to write a #import both DLLs into a test app, I get redefinition errors for the enum.
Does anyone have any experience with this sort of thing?
Many thanks,
Gary
|
|
|
|
|
Include the IDL file containing the enums inside a namspace in your Project1.IDL and Project2.IDL
I think this will solve your problem.
Have a great day ahead!
Regards,
Sohail Kadiwala
(My Blog - http://blogs.wdevs.com/sohail/[^])
modified 21-Apr-21 21:01pm.
|
|
|
|
|
Gary,
Try importing the Type library (using importlib("..")) of the enum idl into the type library definition of your components idl and not anywhere else. This might work.
for eg.. consider ur enum idl as "SampleEnum.idl" and its tlb as "SampleEnum.tlb"... then your component idl shud be like,
#import "SampleEnum.idl"
[...]
interface Izzzzzz : Ixxxxx
{
}
[...]
library xxxxx
{
importlib("SampleEnum.tlb");
// your coclass definition goes here
}
Hariharan.T
|
|
|
|
|
Hi Gurus,
I have to call a function in VB COM, with parameter SAFEARRAY ** (it's originally "ByRef TabList() As String" in VB), as below:
HRESULT bGetTab(SAFEARRAY ** TabList, long* iMaxNumber).
I successfully called it with Smart Pointer without any problem (but seems Smart Pointer is doing early binding, I guess it might not be compatible with the next version of that VB COM).
So, I tried the InvokeHelper to do late binding. It's working with the simple functions generates by ClassWizard, but not with that bGetTab function. Here is my code for InvokeHelper (I have to make it by myself, cause the ClassWizard is not capable to generate for that function)
// Function to get a string table with iMaxNumber elements
// VB Code: Public Function bGetTab(ByRef TabList() As String, ByRef iMaxNumber As Long) As Boolean
BOOL CKMServices::bGetTab(SAFEARRAY **TabList, long *iMaxNumber)
{
BOOL result;
static BYTE parms[] =
VTS_PVARIANT VTS_PI4;
InvokeHelper(GetDispid(this->m_lpDispatch, _T("bGetTab")), DISPATCH_METHOD, VT_BOOL, (void*)&result, parms, TabList, iMaxNumber);
return result;
}
// And how do I call that function
SAFEARRAY *arrTab = NULL;
arrTab = SafeArrayCreateVector(VT_BSTR, 0, iMaxNumber);
if (!arrTab) _com_issue_error(E_OUTOFMEMORY);
if(!m_KMServer->bGetTab(&arrTab, &iMaxNumber))
{// Return custom error message }
I've allocated my TabList before calling. But I'm not sure what the type to put for SAFEARRAY **. I have tried VTS_PBSTR, with the same result (it raised COleException).
Thanks before,
Hany
|
|
|
|
|
Hi all!
I tried to post this in the C# forum, but without replies. I tought I might try here too.
I have a small Interop question:
I have a COM object that takes a structure as in-parameter. One of the fields in the structure is an IID*. When doing this in C++ the code:
GUID rrid = __uuidof( _InterfaceName );
parStruct.riid = &rrid;
works fine.
How would I do this in C#? I have tried several things, but can´t get it to work. The type of the struct-field in C# is intPtr. And the only way I can find such a type, that I can think of, is:
Type t = typeof( _InterfaceName );
System.RuntimeTypeHandle h = t.TypeHandle;
parStruct.riid = h.Value;
But I guess that I am way off here.
Any one that can give me a hand here?
Regards
Mikke
Added info:
Hi again!
I tried to create a C++ .Net project instead, just to try and find a work-around. When I took the COM objects needed and tried to import them into my brand new cpp project i got this error message:
TlbImp warning: The type library importer could not convert the signature for the member 'RobEventParams.riid'.
And a couple of other ones like this one for other similar parameter-structs with riid fields. What does that mean for me? Is it impossible to marshal something from .Net into this COM? The purpose is to set up a sink and recieve events from the COM object, to do this I should send a ref to an object that should recieve the events and the signature of an interface implemented in the receiver. It is the interface "signature" that is the riid, and also the problem here. When I execute my C# code above I get an exception telling me that "No such interface supported". Do I have to submit a non-.net method as a sink here?
Best regards again / Mikke
|
|
|
|
|
I can see why no one responded to your inquiry. The way you phrased it is confusing, even to me, and I read it and then re-read it several times.
The basic concept is that you are trying to write a .NET application that will respond to events fired from a COM object that you have imported.
While it appears that this should be a simple matter, it is actually confusing as hell. I have a copy of the book, ".NET and COM: The Complete Interoperability Guide", by Adam Nathan, that I have learned an immense amount of 'stuff' from. I would highly recommend it, especially if you do this type of thing alot. He has an entire chapter devoted to the subject, "Responding to COM Events", which is about 50 pages long and describes the techniques clearly and in detail.
To be perfectly honest with you, I don't completely understand the matter, and I am reluctant to provide you with confusing information.
However, you are working in the right direction. In his book, Adam Nathan describes the callback mechanisms for both .NET and COM, and, while similar, they differ significantly. Basically, he describes the way the type library importer transforms the Source Interface in order to expose the COM object connection points as .NET events using a number of additional types (these are: an event interface, a delegate, a private class that handles interaction with the connection point, and a private sink class that implements the source interface).
It is just too much information to adequately describe here. I suggest that you consult his book.
|
|
|
|
|
Hi Folks )
i've got a strange problem with BSTRs in my DCOM application.
I'm passing 6 BSTRs in a class object (its properties) to a method on a remote server that has to write these strings in some registry values on a pre-defined key.
I've tried both allocating a BSTR and passing it to the server function (see next few lines
BSTR bsBuffer;
bsBuffer=SysAllocString(OLESTR("Prova"));
theApp.m_pHello->SetName(bsBuffer);
SysFreeString(bsBuffer);
and calling server functions directly passing a string (confiding in the operator= that BSTR involves).
theApp.m_pHello->SetDescription("Prova 02/05/2005");
theApp.m_pHello->SetDriver("0.01a");
theApp.m_pHello->SetName("Prova");
theApp.m_pHello->SetVendor("Execute, Crash & Sigh LTD");
theApp.m_pHello->SetLocalBus("VXI");
theApp.m_pHello->SetFirmware("0.00001a");
//Adding Object
theApp.m_pHello->Add();
Running application there is no errors, no code violations, no abnormal program terminations, NOTHING....
BUT
In the registry I get a strange thing like this (I report values in tabular format)
sDesc=Execute, Crash & Sigh LTD
sDriver=0.00001a
sFirmware=0.00001a
sLocalBus=0.00001a
sName=0.00001a
sVendor=Execute, Crash & Sigh LTD
All server functions do nothing but extract the string part in the BSTR and save it in the registry using Windows API functions.
What can I do?
What can it be?
Thanks a lot in advance,
Moreno.
|
|
|
|
|
Try the first one an don't free the Memory (SysFreeString)
Best now?
|
|
|
|
|
OK, I will not free the memory soon, but WHEN can I free that memory?
I don't want to make a memory-consuming server...
Thanx again....
|
|
|
|
|
Marshaling layer in COM do free for you in the client side if parameter is [in] type and in server side in [out] parameter. You must free memory (SysfreeString) in client side for [out] parameter,...
Try to use _bstr_t type and forget memory alloc and free.
Regards...
|
|
|
|
|