Does anyone know off hand what the API is that is equivalent to VB's GetObject? I want to Create and Instance of an OLE Appication, but i dont want to create a new instance if one is already running. Instead i wish to get its interface pointer and work with the open Instance..

Basically im trying to code in MASM the equivalent to:
Set objXL = GetObject(, "Excel.Application")


' What did we find?..
If Not TypeName(objXL) = "Empty" Then
strMessage = "Excel Running."
Else
strMessage = "Excel Not Running."
End If


However, Its not for Excel for my purposes ;)

Thanks in advanced...
:alright:
NaN
Posted on 2003-04-18 11:02:57 by NaN
Man i dont get it. VB can do this, but there is no such equivalent to be found on the web for C/C++. I know it can be done but im pulling up absolutely nothing from searching...
Posted on 2003-04-18 11:42:19 by NaN
NaN , if you'll get the solution - could you share it with me? I tried to solve such problem, but I could'n do it myself.
Posted on 2003-04-18 11:46:18 by gaidar
After alot of painful searching i found something that comes close:

;238610]Here

The C++ example shows one way. However, the "GetActiveObject" may be a custom function to VC++... I have yet to determine this.
Posted on 2003-04-18 12:57:41 by NaN
IRunningObjectTable::GetObject

I remembered this from a white paper and checked MSDN for ROT.

Is this what you are referring to?

Regards, P1
Posted on 2003-04-18 13:05:41 by Pone
Not sure.. Its definitely in the right train of thought, but not sure if its the right interface to get the job done.

Im trying to transcribe the above C++ source. I got it transcribed. But its still failing on me.....

still hacking at it..

:NaN:
Posted on 2003-04-18 16:10:33 by NaN
Posted on 2003-04-18 18:12:42 by Hiroshimator
Afternoon, Nan.

Attached is Masm code to check whether Excel is running or not.

I've hardcoded in the CLSID for the Excel I have installed (Excel 2k2/XP).
You'll find the CLSID here: HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Excel.Application\CLSID

It seems that all you need to remember when using GetActiveObject is to use CoInitialize/ CoUninitialize.:tongue:
(took me two friggin' hours searching the net and mucking about with VB and C/C++ code to figure that out:mad: )

Cheers,
Scronty
Posted on 2003-04-18 21:53:54 by Scronty
Thanks for the help.. This was a Nusance of a problem. I had envisioned 10min of work to do this much, but in turn it took all day ( :rolleyes: ).

I have now got it working.. but not with out new turn of events. Im transcribed the MS source entirely and it wasnt working. With some debugging, i found out that "GetActiveObject" was actually reteiving a proper interface pointer if Excel was running, however, when i use this pInterface I ended up with crashes every time.

Then it dawned on me. This is a dispatched handle created "on the fly" and i guess this implies to Excel that this interface handle can not be called by Early Binding ( virtual function calls).

So i tried with late binding, using the Dispatch _Invoke method, and voila! This interface handle does work!

The really interesting bit to this adventure is two things:

    [*]The pInterface from a CreateInstance application of Excel does not match the pInterface returned by GetActiveObject, even though they are suppose to be the same interface to the same application. This i can buy rationally (they are objects).
    [*]The pInterface returned from CoCreateInstance will allow early bound call to the "Quit" method by "vf() calling". However, the returned Interface from GetActiveObject will crash if i do the same, but works for late binding to the same "Quit" method via "dm() calling". This Im confused on how the segragation is defined by the running OLE process. They appear to be the same on the surface, and as viewed by ITypeInfo, but the definetely are NOT the same. Its as tho there is a hidden flag saying, I MUST BE LATE BOUND ONLY!.


    This means to be able to link and run to active applications through OLE, i need to have all the methods declaired for the slower late binding. Japtheths ComView (which i still think is a fanstastic piece of work) only provided dm declairations to a specific set of methods/properties. I think his tool will need to be revamped into another version, that will allow the person to select if the generated includes are for early binding, late binding, or both!! For situations when your linking to running processes, and not just creating new ones....

    Japheth?? Wink Wink?? You following this?? ;)
    Your probably starting to hate me by now for all this bug snooping :grin:

    :alright:
    NaN
Posted on 2003-04-18 22:17:18 by NaN
Oh ya, i suppose i should post some source ;)
   xor eax, eax

mov pIUnknown, eax
mov pIDisp, eax
mov clsid, eax


.data
align 4
szStr db "Excel.Application",0
.code

; Force focus to this window ensureing ROT is updated
invoke SetForegroundWindow, hWindow

; Get the Class ID dynamically (Not 100% needed)
Ascii2Unicode addr Buffer, addr szStr, 128
invoke CLSIDFromProgID, addr Buffer, addr clsid

; Do 5 tests for getting the Active Excel Instance
push ebx
xor ebx, ebx
.while ( ebx < 5 )

invoke GetActiveObject, addr clsid, NULL, addr pIUnknown
.if ! eax

invoke vf( pIUnknown, IUnknown, QueryInterface), \
addr pIID_Dispatch, addr pIDisp
mov ebx, 10 ; Will force exit
.endif
invoke Sleep, 1000
inc ebx
.endw
pop ebx

; Show the results
PrintHex pIUnknown
PrintHex pIDisp

.if( pIUnknown )
invoke vf(pIUnknown, IUnknown, Release)
.endif

; See if i caught a something...
.if( pIDisp )

mov edx, pIExcelApp
mov eax, pIDisp

; Show me the Interface Name of the IDispatch type...
invoke GetDispatchType, pIDisp, addr Buffer, 128
PrintString Buffer

; Late binding call via IDispatch::Invoke method (Works!)
invoke MakeInvokeString, 0
invoke InvokeHelp, 12EH, DISPATCH_METHOD, pIDisp, eax, NULL, NULL

; Early binding by determining the function pointer offset
; At compile time, this fails! But works if the handle was
; generated by CoCreateInstance, rather than GetActiveObject.
;
;invoke vf( pIDisp, _Application, Quit )


PrintHex eax, "Released Dispatch"
.else

; No beep and tell me it failed.
invoke Beep, NULL, NULL
.endif


Pay attention to the comments... It seems that while early binding is prefered for speed and is simply easier to do from Assembly, it appears that COM is a moody beotch and will only accept it under special conditions. To date, COM has accepted LateBinding on every attemp with out fail :rolleyes: , so it seems that even at the assembly level, to safely use COM its best to use latebinding as your practice. ( Just cant get away from the properties of VB here... )

:NaN:
Posted on 2003-04-18 22:59:30 by NaN
Hi NaN,

Forgive me for replying so late ;) . Currently other things require most of my attention.

But of course "your wish is a command to me" (literally translated from German).

comview version 1.7.1 has option "generate dispatch helpers for dual interfaces as well" (a silly name, I know, if you find a better one, please tell me). the option is described in more detail in help dialog. possibly this may suffice for your needs.

click here to download

Japheth
Posted on 2003-04-19 03:01:14 by japheth
Your not replying late at all! I was surprised to see you so soon.. ;)

I didnt realize you had this done already! Great!.

As well, i want to pick your brain a bit and see what you think about all this. Im kinda of surprised that while books etc. teach your how to early bind, as well as late bind, that the only truely dependable option is latebinding. Im mean WTF?

Whats your take on this business?
:NaN:
Posted on 2003-04-19 09:56:15 by NaN
Got a Question regarding Windows Stuff:

I wrote an application for work that automated a certain AutoCad task. I designed it at home on my 98SE box, tested and it ran perfectly.

I took it into work and it failed right away on my WIN2000 machine.

I debugged it at work and discovered that the error was from this passage of code (from above):

.data

align 4
szStr db "Excel.Application",0
.code

; Get the Class ID dynamically (Not 100% needed)
Ascii2Unicode addr Buffer, addr szStr, 128
invoke CLSIDFromProgID, addr Buffer, addr clsid


Where the MSDN defines it as:

HRESULT CLSIDFromProgID (

[b]LPCOLESTR[/b] lpszProgID,
LPCLSID pclsid);


I couldnt figure it out at work (with out internet) so i simply hardcoded the key and it took off on the next compile.

Looking at it now my guess is that I need to create a BSTR, by first calling SysAllocString and then converting to WChar.

Is this a correct assumption? Im puzzled why I never got trapped earlier on win98.

:confused:

:NaN:
Posted on 2003-04-22 19:14:24 by NaN
Hi NaN,

it has to be a wide string, not necessarily a BSTR. A BSTR pointer points to a wide string, so a BSTR may be used where a wide string parameter is required (the opposite is not true). The differences are that a BSTR is in all cases allocated dynamically and at offset ptr-4 is the size of the BSTR, so it may contain 00 chars.

Japheth
Posted on 2003-04-23 01:02:05 by japheth
Thanx Japheth for the clarification.

At work today, i but this to the test, and recompiled it, providing a true BSTR and it worked, where simple a WCHAR string it failed.

This is again on Win2000 tho, so i guess being an NT based system it has its view on this clearly defined.
Posted on 2003-04-23 18:48:40 by NaN
Very mysterious, NaN. Perhabs your wide string wasn't "dword aligned"?
Posted on 2003-04-24 01:29:42 by japheth
I should have been... the buffer i used to make the WChar string was 128 bytes long as a LOCAL off the stack. (only other locals were DWORDS).

:NaN:
Posted on 2003-04-24 17:26:50 by NaN