|
Thanks
it's working now
Manoj Kumar Chauhan
|
|
|
|
|
Imported "cominterface->functionname" returns C++ class "_bstr_t", which has a destructor and misleading "operator wchar_t*".
Valid variant is:
str = cominterface->functionname(pass input length here).copy();
With best wishes,
Vita
|
|
|
|
|
Thanks it's also working
Manoj Kumar Chauhan
|
|
|
|
|
If i want to return any variable length string from COM then i can allocate memory in COM and return it to exe (return BSTR*). Finall exe which's using the COM will free the memory. Is this OK?
Yes.
String Manipulation Functions Descriptions
------------------------------------------
SysAllocString Creates and initializes a string.
SysAllocStringByteLen Creates a zero-terminated string of a specified length (32-bit only).
SysAllocStringLen Creates a string of a specified length.
SysFreeString Frees a previously created string.
SysReAllocString Changes the size and value of a string.
SysReAllocStringLen Changes the size of an existing string.
SysStringByteLen Returns the length of a string in bytes (32-bit only).
SysStringLen Returns the length of a string.
There are some C++ classes working with BSTR: CComBSTR, _bstr_t.
How to make same parameter as input/output in COM function?
You can specify [in] for input parameter and [out] for output. I have shown this recently.
How to return more than one string through COM function. suppose if i have function
int func(BSTR inputstring, BSTR* outstring1, BSTR* outstring 2);
Here i want to return 2 strings from this function.
Simple answer is:
int func([in] BSTR inputstring, [out] BSTR* outstring1, [out] BSTR* outstring 2)
But this code will not be working with some scripts, because the basic data for script is VARIANT and not all IDispatch handler can process these data. Moreover, for example, Jscript cannot receive any [out] data at all, but only with [out, retval].
With best wishes,
Vita
|
|
|
|
|
Vi2 wrote: "iostream" object is C++ object, not accessible directly from scripts
True.
Vi2 wrote: and unallowed in COM accordingly
False. It's not allowed in COM automation only.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Automation clients, such as scripts, deals only with BSTR , hence you need to use BSTR s if your COM server needs to support them.
On the other hand, clients such as C++ applications (or even VB6 ones) may use server methods accepting char * .
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
I would like to add an IHTMLElement dynamically to the HTML that contain an "A" ActiveX control.
That I want to add is another "B" ActiveX control.
So.. I programmed in "A" activex source code as below.
I created new element.
/* I deleted bstr, SysFreeString, VARIANT etc.. to understand easily */
IHTMLElement* pObjectElement=NULL;
m_pDoc2->createElement("<object>", &pObjectElement);
pObjectElement->setAttribute("classid", "clsid:AF0DDB60-76F8-4ADC-BF58-563EB7DF2B9D", 0); // "B" ActiveX control's Clsid
pObjectElement->setAttribute("width", "600");
pObjectElement->setAttribute("height", "400");
and.. attached it to the bodyElement.
m_pDoc2->get_body(&pElement);
pElement->QueryInterface(IID_IHTMLBodyElement, (LPVOID*)&pBody);
pBody->QueryInterface (IID_IHTMLDOMNode, (LPVOID*)&pParent);
pObjectElement->QueryInterface (IID_IHTMLDOMNode, (LPVOID*)&pChild);
pParent->appendChild (pChild, NULL);
It works well.
And.. I created another new element "param" to send "MyValue" to the "B" ActiveX control.
/* I deleted bstr, SysFreeString, VARIANT etc.. to understand easily */
IHTMLElement* pParamElement=NULL;
m_pDoc2->createElement("<param>", &pParamElement);
pParamElement->setAttribute("name", "src");
pParamElement->setAttribute("value", "MyValue");
and... attached it to the object element.
/* I inserted this code before object element is appended to the body element. like this..
* pChild->appendChild (pParam, NULL);
* pParent->appendChild (pChild, NULL);
*/
pParamElement->QueryInterface (IID_IHTMLDOMNode, (LPVOID*)&pParam);
pChild->appendChild (pParam, NULL);
But It doesn't work.
"B" ActiveX control couldn't receive "MyValue".
There are any problems in "B" ActiveX control. It works well in common situation.
so.. I thought it failed to append <param> to <object> element.
so, I appended a code to confirm whether param element is contained or not.
Surprisingly, <param> could find in it.
...I really really... don't know how I can solve this problem.
If anybody knows it, please answer me.
|
|
|
|
|
intresting . how about using setinnerhtml function .
|
|
|
|
|
hi,
i want to define an enum type variable on the Interface ,
so i have defined an enum within interface and then take a property from this enum,
but have encountered with a compile time error !?
what is my mistake and what is its solution?
interface IXFSReceipt : IDispatch
{
enum RPtrResolution
{
RPTR_RESOLUTION_LOW,
RPTR_RESOLUTION_MEDIUM,
RPTR_RESOLUTION_HIGH,
RPTR_RESOLUTION_VERYHIGH
};
HRESULT Resolution([out, retval] RPtrResolution* pVal);<<<<<<<< ERROR1
HRESULT Resolution([in] RPtrResolution newVal);
};
ERROR1 : error MIDL2025 : syntax error : expecting a type specification
|
|
|
|
|
Don't be afraid to search through the .IDL files that come with the compiler or SDK. On my system I searched all the .IDL files in "C:\PROGRAM FILES\MICROSOFT SDK\INCLUDE" for the word enum . Here's the first example:
typedef enum tagSCRIPTSTATE {
SCRIPTSTATE_UNINITIALIZED = 0,
SCRIPTSTATE_INITIALIZED = 5,
SCRIPTSTATE_STARTED = 1,
SCRIPTSTATE_CONNECTED = 2,
SCRIPTSTATE_DISCONNECTED = 3,
SCRIPTSTATE_CLOSED = 4,
} SCRIPTSTATE ;
[
object,
uuid(DB01A1E3-A42B-11cf-8F20-00805F2CD064),
pointer_default(unique)
]
interface IActiveScriptSite : IUnknown
{
HRESULT GetLCID(
[out] LCID *plcid
);
HRESULT GetItemInfo(
[in] LPCOLESTR pstrName,
[in] DWORD dwReturnMask,
[out] IUnknown **ppiunkItem,
[out] ITypeInfo **ppti
);
HRESULT GetDocVersionString(
[out] BSTR *pbstrVersion
);
HRESULT OnScriptTerminate(
[in] const VARIANT *pvarResult,
[in] const EXCEPINFO *pexcepinfo
);
HRESULT OnStateChange(
[in] SCRIPTSTATE ssScriptState
);
HRESULT OnScriptError(
[in] IActiveScriptError *pscripterror
);
HRESULT OnEnterScript(void);
HRESULT OnLeaveScript(void);
}
Steve
|
|
|
|
|
You should use the full name for enum, i.e. "enum RPtrResolution", because of C nature of MIDL compiler. For example,
HRESULT Resolution([out, retval] enum RPtrResolution* pVal);
HRESULT Resolution([in] enum RPtrResolution newVal);
OR you should use a "typedef" statement, suggested by Stephen Hewitt.
typedef enum RPtrResolution
{
...
} RPtrResolution;
With best wishes,
Vita
|
|
|
|
|
Hey!
I have some trouble when trying to pass an array of data through an event from an ActiveX class.
My function looks like this:
void MycFunction()
{
SAFEARRAY * m_psaVal;
unsigned char HUGEP *m_pVal;
m_psaVal = SafeArrayCreateVector(VT_UI1, 0, 4096);
HRESULT hr = SafeArrayAccessData(m_psaVal, (void HUGEP**) &m_pVal);
for (int i = 0; i < (m_psaVal->rgsabound)->cElements; i++)
{
m_pVal[i] = static_cast<unsigned char="">(0);
}
SafeArrayUnaccessData(m_psaVal);
m_pVal = 0;
CComVariant Values(m_psaVal);
FireOnNewBuffer(Values);
}</unsigned>
And:
void FireOnNewBuffer(VARIANT Values)
{
FireEvent(eventidOnNewBuffer,EVENT_PARAM(VTS_VARIANT), Values);
}
However, when generating the event my application crashes because of an NullReferenceException.
I have no idea what I am doing wrong, all my other events (not passing arrays) work fine. Can anyone help me on this one?
|
|
|
|
|
CComVariant Values(m_psaVal) is only visible in the function. Create with new
Greetings from Germany
|
|
|
|
|
Okay, so I changed to:
CComVariant Values = new CComVariant(m_psaVal);
But I still get the same error.
It sounded like the solution though.
|
|
|
|
|
Hello Hampus@foi,
I see 2 problems in your code :
1. The 2nd parameter to FireEvent() function is EVENT_PARAM(VTS_VARIANT). This means that the 3rd parameter should be a pointer to "Values".
As a further suggestion, make the "Values" parameter to FireOnNewBuffer() a VARIANT reference (i.e. VARIANT&) instead of a straight VARIANT type. Using a reference saves space and improves performance. Using a VARIANT type would entail copying of the original "Values" from MycFunction() to the stack of FireOnNewBuffer().
Hence a better definition for FireOnNewBuffer() is as follows :
void FireOnNewBuffer(const VARIANT FAR& Values)
{
FireEvent(eventidOnNewBuffer,EVENT_PARAM(VTS_VARIANT), &Values);
}
2. The use of CComVariant for a SAFEARRAY is not appropriate :
CComVariant Values(m_psaVal);
This is because there are no CComVariant constructors that take a SAFEARRAY*.
Instead, I suggest using a VARIANT type :
//CComVariant Values(m_psaVal); // <-- comment out.
VARIANT Values;
VariantInit(&Values);
VariantClear(&Values);
V_VT(&Values) = VT_ARRAY | VT_UI1;
V_ARRAY(&Values) = m_psaVal;
FireOnNewBuffer(Values);
Hope the above helps.
- Bio.
|
|
|
|
|
Excellent, it works perfectly!
You are the greatest, thank you very much!
|
|
|
|
|
Most welcome, Hampus@foi.
|
|
|
|
|
I have Automation object implemented as a local server (.exe). Client creates it through CreateDispatch(...). Default behavior for Automation, when client is closing, is to destroy all COM stuff in OleUninitialize(). As a default - it's ok, but I'm trying to run my server disconnected from the client as it has to perform very lengthy operations.
If I set dispatch's m_bAutoRelease to FALSE, it keeps my dispatch in the runningobject table, nevertheless server's MainFrame window gets WM_DESTROY and WN_NCDESTROY and server gets closed.
Attempt to set (in server) AfxOleUserContorl(TRUE), while calling server very first time, seems to have no effect on server default distruction.
Is there any way to change the default behavior and avoid local server destruction (closing) ?
|
|
|
|
|
The server COM is running in the client threads, so it gots terminated with it. :
For lengthly and repeated threads it is use to write services. Or create a own COM-Thread (App-Server) to which clients can connect (via RPC).
I hope it will help.
Greetings from Germany
|
|
|
|
|
Terminology on COM-Automation is NFG.
Yes, I know that if I'm calling an InProcServer (put it simply DLL) it will run in the client appartment using its main thread and will be terminated upon Client closing. All fine with this logic, but I'm calling a LocalServer (put it simply an .exe program), so calls are marshaled to my executable. Executable has its own tread(s) (process). All I want - to be in control of closing my running Executable, which is a separate process (acording to docs).
Thx for reply.
Greetings from Canada.
|
|
|
|
|
Hi All, I recently developed a shared COM Addin using VB.Net and Outlook 2003. It works great on local machine but when I install it on Terminal server it doesn't work.
My Addin get installed on Windows 2003 Terminal server with the initial Loadbehavior = 2Hex value under the HKEY_LOCAL_MACHINE in registry. It starts working when I change it to 3Hex. But as soon as another user logs in on termail server and starts outlook, the loadbehavior values becomes 2Hex again and my Addin stops working for every user.
Any idea why registry is being changed by every user session. I will appreciate your response.
Thanks
|
|
|
|
|
hi to all,
i have created a com object with c# and my output project is *.dll,
now i nead to export it to .lib file, how to do this work?
so thanks
bye
|
|
|
|
|
Where can I find the exact steps required to do this? I don't want to trust a new dll to properly unregister COM classes registered by a previous version of that dll, so before calling DllRegister whatever, I want to make sure my registry is cleaned of all traces of a component.
|
|
|
|
|
Have a look at [^].
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
the standard way is to call as admin "regsvr32 /u *dll"
But it depends on the implementation if it does every thing right.
Or install the dll on a fresh system and compare registry before and after. But it can also be, that the dll is writing something at runtime.
A proper COM Server uses the same CLSIDs while it is compatible and use others if there is no compatibility.
Greetings from Germany
|
|
|
|
|