|
How can i get back a string from a COM method call?
I use this dispatch params:
DISPPARAMS DispatchParams;
DispatchParams.cArgs=3;
DispatchParams.rgvarg = new VARIANTARG[3];
DispatchParams.rgvarg[0].vt = VT_BYREF|VT_BSTR;
DispatchParams.rgvarg[0].pbstrVal = &bstrDocId;
DispatchParams.rgvarg[1].vt = VT_BYREF|VT_I4;
DispatchParams.rgvarg[1].plVal = &llngFlags;
DispatchParams.rgvarg[2].vt = VT_I4;
DispatchParams.rgvarg[2].lVal = 0;
DispatchParams.rgdispidNamedArgs=NULL;
DispatchParams.cNamedArgs=0;
if the bstrDocId is a BSTR then the invoke returns No such interface supported, if i use CComBSTR then the invoke succeeds but the result is that the bstrDocId becomes NULL. I don't understand this, how can it be NULL if it is not a pointer? If i initialize the CComBSTR with an exact length then the invoke also returns the "Nos such interface supported" error.
If anybody knows how to get back a string i would be pleaseful to see it.
dzsigit
|
|
|
|
|
Looking at this, the signature for the method you're calling is:
HRESULT somename([in,out]BSTR* docID, [in,out]long* flags, long x)
Is this correct?
Steve S
|
|
|
|
|
|
AFAIK, you're using the illegal order of the arguments for Invoke - it should be the REVERSED order.
MSDN: "The arguments are passed in the array rgvarg[ ], with the number of arguments passed in cArgs. The arguments in the array should be placed from last to first, so rgvarg[0] has the last argument and rgvarg[cArgs -1] has the first argument. The method or property may change the values of elements within the array rgvarg, but only if it has set the VT_BYREF flag. Otherwise, consider the elements as read-only."
So your called function looks like
HRESULT somename(long x, [in,out]long* flags, [in,out]BSTR* docID)
instead of your function
long SelectDoc([in, out] BSTR* tstrDocID, [in, out] long* tintFlags, [in] long tintWindow);
With best wishes,
Vita
|
|
|
|
|
Doh!
I should have spotted that too! I blame the painkillers.
Steve S
"Of all the things I've lost, I miss my mind the most"
|
|
|
|
|
Thanks for your help, but it still doesn't work. I've tried with MFC and it throws the same error.
Here is the code, maybe you can see something in it.
HRESULT hr;
OLECHAR FAR* szMember = L"SelectDoc";
DISPID DispatchID;
IDispatch * pDispatch;
IUnknown * pUnknown;
long llngFlags=0;
BSTR bstrDocId=SysAllocStringLen((OLECHAR*)"xxx", 256);
long llngReturn;
DISPPARAMS DispatchParams;
DispatchParams.cArgs=3;
DispatchParams.rgvarg = new VARIANTARG[3];
DispatchParams.rgvarg[0].vt = VT_I4;
DispatchParams.rgvarg[0].lVal = 0;
DispatchParams.rgvarg[1].vt = VT_BYREF|VT_I4;
DispatchParams.rgvarg[1].plVal = &llngFlags;
DispatchParams.rgvarg[2].vt = VT_BYREF|VT_BSTR;
DispatchParams.rgvarg[2].pbstrVal = &bstrDocId;
DispatchParams.rgdispidNamedArgs=NULL;
DispatchParams.cNamedArgs=0;
CoInitialize(NULL);
CoCreateInstance(..)
pUnknown->QueryInterface(..)
pDispatch->GetIDsOfNames(..)
hr = pDispatch->Invoke(DispatchID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &DispatchParams, (VARIANT*)&llngReturn, NULL, NULL);
MFC code
COleDispatchDriver disp;
COleException* e=new COleException();
IDispatch *pdisp;
DISPID dispid;
OLECHAR FAR* szMember[1];
HRESULT hresult;
disp.CreateDispatch(..)
static BYTE parms[] = VTS_PBSTR VTS_PI4 VTS_I4;
pdisp = disp.m_lpDispatch;
szMember[0] = L"SelectDoc";
pdisp->GetIDsOfNames(IID_NULL, szMember, 1, LOCALE_SYSTEM_DEFAULT , &dispid);
long llngReturn;
long llngFlags;
BSTR bstrDocId=SysAllocString(..);
disp.InvokeHelper(dispid, DISPATCH_METHOD, VT_I4,(void*)&llngReturn, parms,&bstrDocId , &llngFlags, (long)0);
dzsigit
|
|
|
|
|
dzsigit wrote:
long llngReturn;
...
hr = pDispatch->Invoke(..., &DispatchParams, (VARIANT*)&llngReturn, ...);
I think that it's a bad practice to make the ambiguous casting to avoid the compiler error.
In any case the E_NOINTERFACE can be a valid HRESULT which can mean that there is no such Document as you specify.
With best wishes,
Vita
|
|
|
|
|
What kind of Document do you mean? I only want to call my function that is written in .Net.
My function's return type is long, how can i get back a long value if i don't cast it to VARIANT *? I've read a lot of articles and the return value was everywhere casted like that.
dzsigit
|
|
|
|
|
If your function's return type is long, then it isn't an HRESULT.
Conventionally, automation methods all return an HRESULT to indicate success or failure, and if there is a 'logical' return value, it can be indicated by using the [retval] attribute on the appropriate value.
What is the actual IDL/ODL code for your method please...
Steve S
|
|
|
|
|
The IDL code
[id(0x6002001a)]
long SelectDoc(
[in, out] BSTR* tstrDocID,
[in, out] long* tintFlags,
[in] long tintWindow);
dzsigit
|
|
|
|
|
OK, next question. You have tstrDocID and tintFlags as [in,out]. Does that mean you could pass in both of these and pass back different ones and that's what your COMponent is expecting to deal with?
Typically, you would see this written as
[id(0x6002001a)]
HRESULT SelectDoc([in,out]BSTR* tstrDocID, [in,out]long* tintFlags, [in] long tintWindow, [out,retval]long* pResult);
This makes it easy to return failures, via an unsuccessful HRESULT (top bit set),
and a return value flagged in this way is accessible by conventional assignment in environments such as VB.
Steve S
|
|
|
|
|
That's right.
I have this function written in VB.Net and at first it automaticaly generated the interface. After that i wrote an interface where i could influence the generated idl code. I've tried other functions where BSTR* and long* were the parameters and they worked fine. With this function there is something wrong with the order of the parameters (i think), but i've tried different orders even those that i didn't think it would work and none of them succeded.
dzsigit
|
|
|
|
|
Hi all
I've created an ActiveX control, and an Application derived form CFormView.
in the FormView of Apllication, i insert this ActiveX control.
In ActiveX control, how can i get the window of the application that use the it
Thanks
|
|
|
|
|
Is there some way on which I could register a dll or ocx not using Regsvr32.exe?
I want to register dlls programatically, knowing only the path and dll name.
I also want to know if it has been registered or not.
Is there an API that does this?
Please help. Thanks.
SDE
|
|
|
|
|
Load dynamically the DLL and call the function DllRegisterServer, for registration a server
|
|
|
|
|
|
Hi!
With CreateFromFile() I am able to open an excel file in my ole
container application.
I want to embed excel sheet in my container applicatio and want to
display contents of a file, but i dont want to use CreateFromFile(), I
just want to pass raw data as input.
Which function shall I use,CreateFromClipboard() or CreateFromData().
I am running on Win2k and have office2k.
Thanks
Anshu
|
|
|
|
|
I have a .Net application that i want to access from a VC++ client as a COM object. Everything goes fine until i want to pass parameters. The description of the function is:
in VB.Net
Public Function SelectDoc(ByRef tstrDocID As String, ByRef tintFlags As Integer, ByVal tintWindow As IntPtr) As Integer
the idl description is:
long SelectDoc(
[in, out] BSTR* tstrDocID,
[in, out] long* tintFlags,
[in] long tintWindow);
i call it with invoke
hr = pDispatch->Invoke(DispatchID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &DispatchParams, (VARIANT*)&lngReturn, NULL, NULL);
with the following params:
DISPPARAMS DispatchParams;
DispatchParams.cArgs=3;
DispatchParams.rgvarg = new VARIANTARG[3];
DispatchParams.rgvarg[0].vt = VT_BYREF|VT_BSTR;
DispatchParams.rgvarg[0].pbstrVal = &bstrDocId;
DispatchParams.rgvarg[1].vt = VT_BYREF|VT_I4;
DispatchParams.rgvarg[1].plVal = &lngFlags;
DispatchParams.rgvarg[2].vt = VT_I4;
DispatchParams.rgvarg[2].lVal = 0;
DispatchParams.rgdispidNamedArgs=NULL;
DispatchParams.cNamedArgs=0;
The invoke return 0x80040002 witch means No such interface supported
I've tried to change the attribute of the class witch implements the method
(AutoDual, AutoDispatch, None) and it didn't work. I've made an interface for the class because i've read somewhere that i should do this.
Can anyone please help me?
dzsigit
|
|
|
|
|
Can be LOCALE_USER_DEFAULT instead of LOCALE_SYSTEM_DEFAULT.
Might be useful to post your entire idl file, so at least the interface shows.
The attribute added to the VB.NET code matters. If it this doesn't tell the compiler to mark the interface as automation enabled, then yes you are pretty much sure that Invoke will fail.
You might be interested in this article : http://www.codeproject.com/dotnet/nettocom.asp
RSS feed
|
|
|
|
|
Thanks for that article it seemed to solve my problem, but it still doesn't work.
The error is still "No such interface supported".
|
|
|
|
|
There can be two reasons at least :
- bad attribute usage in the VB.NET code : hard to help without knowing anything about your code and your resulting idl.
- type-library not in the gac : make sure to read the comments (regasm, ...) in the article previously mentioned. In some cases, there are things that must be done manually.
RSS feed
|
|
|
|
|
I've found the problem
I had to use CComBSTR not BSTR type, and it works.
Thanks again
|
|
|
|
|
Hi all
I'm deveploping an Application, and i need a Component that can convert image( may be .gif, or png..) to flash.
help me
thanks
|
|
|
|
|
Hi all,,,
I make an application that will connect to a remote database on a Win98 machine..
I want to use the 3-tier architecture and call Middle tier components on the Win98 machine
can this be done using DCOM or any other method ?
any links - suggestions are appreciated
|
|
|
|
|
How to make COM+ event class and subscriber in Visual C++ .NET
|
|
|
|
|