|
Hi,
I'm working on a VB.NET project and my objects should be reachable using COM. My problem is that these objects have overloaded methods, properties, which seems problematic.
For example I have a collection class with two item properties:
Default Public ReadOnly Property Item(ByVal Key As String) As Object
and
Default Public ReadOnly Property Item(ByVal Index As Integer) As Object
When I try to use an object of this class in a COM only environment - like MS Word - there only one Item can be seen, and allways the first. So using the order above I can query collection items only by Key, when I change the order I can query only by Index.
This problem does not occour under .NET.
My question is: how to do VB.NET overriding, polymorphism to satisfy COM requirements?
(K)
(K)
|
|
|
|
|
Because overloading isn't supported in COM, hence a COM-Callable Wrapper (CCW) can't be created properly. Choose one or the other, but not both.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
What's the VARIANT equivalent type?
--
You're entertaining at least.
|
|
|
|
|
|
Is this always true: object <=> VARIANT?
--
I am perpetual, I keep the country clean.
|
|
|
|
|
If you don't know what type, and specify none, the default is Object, in non-.NET VB ( ) that was Variant.
However, do not convert "As Any" in API declaratioins to "As Object", because you'll get an error like "not set to an instance of an object"..., use the most convenient type instead, if you are using more of them, define different functions referring to the same alias
greetz
*Niels Penneman*
Software/Dev Site Personal Site
|
|
|
|
|
I have a COM DLL written in C++/ATL. I added a new method to one of the interfaces and altered my testbed to call this new method.
I then went and registered an earlier version of the DLL which doesn't contain the new method. Not surprisingly, an exception is raised when the testbed tries to call the method. I can catch this with a try/catch handler, but I still get an unrecoverable exception when the calling function exits (see code snippet below).
Is there anyway of interrogating the interface to see if the method exists?
If not, is there I way my app can continue to run gracefully? This final 0xC0000005 exception is a bit of a showstopper.
Thanks,
Gary
---
void func()
{
::CoInitialize(NULL);
try
{
CComPtr<IMyInterface> MyInt;
MyInt.CoCreateInstance(CLSID_MyInterface);
MyInt->NewMethod();
}
catch(...)
{
AfxMessageBox("eek");
}
} // exception 0xC0000005 thrown here
|
|
|
|
|
Gary Chapman wrote:
Is there anyway of interrogating the interface to see if the method exists?
You need to call GetIDsOfNames after CoCreateInstance to determine if a method exists on a given interface.
The way your code is written will not work because even if the method exists, you cannot call it as if it is early-bound (you are doing late-binding). What you need to call is the Invoke method of IDispatch.
[Edit] As Bo Hunter pointed out, I was wrong in saying the code won't work. [/Edit]
COM programming is very complicated without help from libraries like ATL or MFC. However, you can reuse some of my code[^] to save a lot of time.
My articles and software tools
|
|
|
|
|
The interface would have to implement IDispatch would'nt it?
If CLSID_Myinterface is a valid coclass then this code should
work.
This is perfectly valid code here.
BOOL OpenLinkUsingCom(TCHAR* pLink, int how, HWND hWnd)
{
IUniformResourceLocator* pLocator;
HRESULT hr = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, IID_IUniformResourceLocator, (LPVOID*)&pLocator);
if (SUCCEEDED(hr))
{
hr = pLocator->SetURL(pLink, IURL_SETURL_FL_GUESS_PROTOCOL);
if (SUCCEEDED(hr))
{
URLINVOKECOMMANDINFO ivci;
ivci.dwcbSize = sizeof(URLINVOKECOMMANDINFO);
ivci.dwFlags = 0;
ivci.hwndParent = hWnd;
switch (how)
{
case OPEN:
ivci.pcszVerb = _T("open");
break;
case EDIT:
ivci.pcszVerb = _T("edit");
break;
case PRINT:
ivci.pcszVerb = _T("print");
break;
default:
ATLASSERT(0);
}
hr = pLocator->InvokeCommand(&ivci);
}
}
if (pLocator)
pLocator->Release();
return (SUCCEEDED(hr));
}
Please tell me if I am wrong.
Thank You
Bo Hunter
|
|
|
|
|
|
If interface being tested is derived from IDispatch, the GetIDsOfNames is a simplest way to see it.
The second way is the ITypeInfo::GetIDsOfNames for non-dual interface if the Type Library is accessible (either by LoadRegTypeLib or by LoadTypeLib).
PS
It is a bad practice to change the contents of interface without the changing of its IID.
With best wishes,
Vita
|
|
|
|
|
If the interface had already been published then yes
you should give it a new name but for testing I don't
think that is really relevent.
Thank You
Bo Hunter
|
|
|
|
|
Hello,
i am a beginner at COM. Please tell me if its necessary to create class factory to make a COM object. If not then when is it exactly necessary.
Thank you
|
|
|
|
|
Yes, it is COM rule that declares that COM server should present own class objects (i.e. class factories).
With best wishes,
Vita
|
|
|
|
|
Solution: Compile and register proxy DLL.
I am curious though as to what proxy I got back in the client process. One would imagine QueryInterface() should bite me when I try to query for an interface for which it, obviously, cannot proxy. It seemed as if it was giving me a proxy for a totally different (but class related) interface - vtable order and parameter signatures seemed to matter. Other methods than DoOperation worked if and only if they matched another interface's vtable order/method signature.
This is my scenario:
I have an exe automation server. I register an object in the running object table. The object exposes this interface:
[ ... ] interface IY : IDispatch {
[id(y)] DoOperation();
}
[ ... ] interface IX : IDispatch {
[propget, id(x)] Y([out, retval] IY** ppY);
}
Registration of the object in the exe server works just fine, and so does acquiring the object in the client application. The call to IX::get_Y() works without flaws as well. However, calls do IY::DoOperation fails miserably. It crashes in an instance at 0x00000000 - it tries to execute code at that adress..
Sounds like the proxy object has a screw loose. Has anybody dealt with a similar problem before? If so, care to share a solution?
--
You copy and paste yourself into my brain.
You always find your way back into my brain.
|
|
|
|
|
hi,
I have a problem when releasing the IDirectInput8Device interface as below.
if (m_lpdirinde8Device)
{
m_lpdirinde8Device->Unacquire();
m_lpdirinde8Device->Release();
m_lpdirinde8Device = NULL;
}
But it hangs at the release. This happens only if I create an effect on this device. Can somebody give a hint why release hangs?
Thanks
Manju
|
|
|
|
|
I don't know exactaly what may have caused the Release to crash from looking at the code you listed, but the last time this happened to me was when my IUnknown:Release was called while there was a pointer still open or a memory buffer that was not closed/freed (be it a string without an end character or a Malloc-ed memory space) before the call to Release.
This MAY be the problem, as it what causes a similar problem for me, but there could be other factors, like an improper declaration of the Release in your COM class declaration and so on.
|
|
|
|
|
I'm a bit confused about Exchange client extensions vs Outlook rules implementation. How do I write a custom rule for Outlook in the context of a C++ COM addin? I think apart from the COM addin support I just need to implement IExchangeRuleXXX(),IExchExt interfaces and register the dll as an Exchange client extension?
Thanks for your time.
|
|
|
|
|
I've tried to used this article http://www.codeproject.com/csharp/CsAutomateWord.asp?target=Word to create a character sheet.
I have a CCharacter class, that contains all information about a character, and I want to generate a MS Word document with these information.
So I've created .dot document, with thinks like
Name _Name_ Age _Age_
in arrays (I've tried also without the array, directly in the text). _XXX_ is code that I will use for replacement.
Now, to the code:
// Create a Word application
Word.ApplicationClass vk_word_app = new Word.ApplicationClass();
// Open the .dot
object FileName =Directory.GetCurrentDirectory()+"\\Models\\Sheet.dot";
Word.Document vk_my_doc = vk_word_app.Documents.Open(...
// Create a new document
Word.Document vk_new_doc = vk_word_app.Documents.Add((...
// Copy the .dot into the new document
vk_my_doc.Select();
vk_word_app.Selection.Copy();
vk_new_doc.Select();
vk_word_app.Selection.PasteAndFormat(Word.WdRecoveryType.wdPasteDefault);
// close the .dot
vk_my_doc.Close( ref vk_false, ref vk_missing, ref vk_missing );
All the previous steps work. I get a new document, build from my template.
Now, I'd like to fill it with actual information. So I do this
// Select the new doc
vk_new_doc.Select();
// Define some variable
object vk_false = false;
object vk_true = true;
object vk_num = Word.WdFindWrap.wdFindStop;
object vk_find = "_Nom_";
object vk_replaceWith = Name_Familly; // This one is a member of CCharacter class
object vk_replace = Word.WdReplace.wdReplaceOne;
// Try to replace the text
vk_word_app.Selection.Find.Execute( ref vk_find,
ref vk_false, ref vk_false,
ref vk_false, ref vk_false, ref vk_false, ref vk_true,
ref vk_num, ref vk_false,
ref vk_replaceWith, ref vk_replace, ref vk_false,
ref vk_false, ref vk_false, ref vk_false );
And... it doesn't work.
I got this error:
System.Runtime.InteropServices.COMException (0x800706F7): Le relais a reçu des données incorrectes.
at Word.Find.Execute(Object& FindText, Object& MatchCase, Object& MatchWholeWord, Object& MatchWildcards, Object& MatchSoundsLike, Object& MatchAllWordForms, Object& Forward, Object& Wrap, Object& Format, Object& ReplaceWith, Object& Replace, Object& MatchKashida, Object& MatchDiacritics, Object& MatchAlefHamza, Object& MatchControl)
My form close, the word doc stays opened.
"Le relais a reçu des données incorrectes" would translate as "incorrect data received".
Any idea of a way to solve this would be greatly welcomed!
|
|
|
|
|
I want to figure out how exaxtly Remember my password and username is implemented in messengers or any desktop application say Yahoo messenger.
|
|
|
|
|
There is no concrete way. Remember that any key you use to encrypt such information can relatively easily be extracted and used to decrypt passwords, so don't do that.
A good mechanism would be to hash the password using MD5 or SHA1 (both good hash algorithms) before transmitting across the 'net or storing. These two algorithms are mathematically proven to be irreversable. If the user has the "Remember Password" option checked, then read the value from a file or the registry - which is the password hash - and transmit it without hashing it again (which is also hingent on whether "Remember Password" is checked). This is pretty good for secure storage, as well as somewhat secure transmission.
On the server side, you simply store the password hash and compare the hash sent by the user with the hash stored in the database (or whatever).
One warning, though - sending just the hash is subject to replay attacks. If someone intercepts that hash, they merely have to send it with some program they could right and get access to the user's information. Instead, before sending the hash, request another hash that is used to hash the password hash, but that hash should be reversible. When it gets to the server, extract the original password hash and compare. This is known as a challenge-response mechanism, and there's several ways to do it. Trying googling for more details. Note: digest authentication in web browsers use this mechanism, so you could start there if you like. There is an RFC for it, so try looking at IETF RFC Page[^].
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
That was highly Fundu stuff. Need time to digest it. Then I will get back to U.
Thanx
|
|
|
|
|
I want to develop a application which will connect me directly to yahoo messenger window. i.e entering username and password in Login window will be handled by my application. Don't know how to do it?
|
|
|
|
|
I am not familiar with the workings of the Yahoo messenger and its server.
Sounds like you want to develop a custom client. One solution is winsock. Just look up the protocol that the message server understands.
Kuphryn
|
|
|
|
|
That is the problem I am facing. There are no standard protocols. I just want to some how write in the Edit Boxes and I am done with it
|
|
|
|
|