PDA

View Full Version : COM_GetObject()



marcel
31-10-2007, 14:47
Hi,

I was looking at the script examples for COM. Amazing! I saw the Excel example. I discovered that when I already have an Excel process running a second Excel process is added.

Is it possible to add a new command to thinBasic named as COM_GetObject() that looks for an already running identical process and returns the pointer to that running process? That would be a great benefit above the OLE_CreateObject() that every times creates a new object.

Kind Regards,

Marcel

ErosOlmi
31-10-2007, 15:42
Ciao Marcel,

unfortunately COM module is not much developed so far. Usually we add new features when needed or asked.
I'm sure Roberto will have a look and see if he can dev what you asked. He is in charge of COM module.

Ciao
Eros

marcel
31-10-2007, 15:56
Hello Eros,

Thanks for the answer. I'll keep looking when the command pops up in the ADD list when a new version is published.

Regards

Marcel

RobertoBianchi
01-11-2007, 15:31
Hi Marcel,

I'm try to add the COM_GetActiveObject() functions but until now it works only if the previous instance is started by same process that run COM_GetActiveObject().
So not very useful but always a step forward.

Regards,
Roberto

marcel
01-11-2007, 23:50
Hello Roberto,

Thanks for acting so quickly.

It is indeed a step in the right direction. I knew this command from another language. GetObject(ObjectName as string,ProgramId as string) When the OLE object doesn't exist it is created otherwise the object pointer is returned.



oWord = GetObject("","word.application")
oWord.Documents.Add


I use it very often for working with Word, Excel or Outlook.

Regards,

Marcel

RobertoBianchi
02-11-2007, 09:18
Marcel,

thanks for the info.
The COM_GetObject() is already developed but it doesn't work as you pointed out, I'll check ASAP.

Bye,
Roberto

José Roca
02-11-2007, 09:47
Roberto,

VB's GetObject calls the API function GetActiveObject, and VB's CreateObject calls the API function CoCreateInstance.

You can use GetActiveObject to retrieve a pointer to a running object that has been registered with OLE calling the RegisterActiveObject API function, as Office applications do, but not to an unregistered running object. If multiple instances of, for example Excel, are running, GetActiveObject attaches to the instance that is launched first. If you then close the first instance, another call to GetActiveObject attaches to the second instance that was launched, and so forth.

RobertoBianchi
02-11-2007, 11:49
Hi José,

thanks for your clarifications.
Into the thinbasic_com.dll module (that is written in C) I've implemented the COM_GetActiveObject() as a call to the GetActiveObject() API that seems work successfully, I mean it detect a if Excel is already started and if true it returns an handle to it. Probem begins (invalid handle into GetIDsOfNames) if I use the handle to set some object's properties as showed in the following script example:


uses "COM"

%NUMBER_OF_PARAMETERS = 3

dim pXlApp, pXlBooks, pXlSheet AS DWORD
dim vParam(%NUMBER_OF_PARAMETERS), vRetVal AS VARIANT
dim hr, i, n AS LONG

pXlApp = COM_GetActiveObject("Excel.Application")

IF pXlApp = 0 THEN
pXlApp = COM_CreateObject("Excel.Application")
msgbox 0, "COM_CreateObject() returned " + pXlApp
else
msgbox 0, "COM_GetActiveObject() returned " + pXlApp
end if

IF COM_Succeeded(hr) THEN
for i = 1 to %NUMBER_OF_PARAMETERS
COM_VariantInit(vParam(i))
next
vParam(1) = 1
if COM_Succeeded(COM_Execute(pXlApp, "Visible", %TB_DISPATCH_PROPERTYPUT, 1, vParam(1), 0)) then
msgbox 0, "Now Excel should be visible!"
COM_VariantInit(vRetVal)
if COM_Succeeded(COM_Execute(pXlApp, "Workbooks", %TB_DISPATCH_PROPERTYGET, 0, 0, vRetVal)) then
pXlBooks = vRetVal
if COM_Succeeded(COM_Execute(pXlBooks, "Add", %TB_DISPATCH_METHOD, 0, 0, 0)) then
msgbox 0, "A new workbook should be added!"
else
msgbox 0, "Add workbook fails"
end if
if COM_Succeeded(COM_Execute(pXlApp, "ActiveSheet", %TB_DISPATCH_PROPERTYGET, 0, 0, vRetVal)) then
pXlSheet = vRetVal
vParam(1) = "ThinBASIC"
if COM_Succeeded(COM_Execute(pXlSheet, "Name", %TB_DISPATCH_PROPERTYPUT, 1, vParam(1), 0)) then
msgbox 0, "ActiveSheet name should be changed!"
for i = 1 to 20
for n = 1 to 5
vParam(3) = i
vParam(2) = n
vParam(1) = "Hello"
COM_Execute(pXlSheet, "Cells", %TB_DISPATCH_PROPERTYPUT, %NUMBER_OF_PARAMETERS, vParam(1), 0)
next
next
if COM_Succeeded(COM_Execute(pXlApp, "Quit", %TB_DISPATCH_METHOD, 0, 0, 0)) then
msgbox 0, "Great!"
end if
end if
end if
end if
else
msgbox 0, "Visible fails"
end if
END IF

if isfalse(COM_Succeeded(COM_Release(pXlSheet))) then
msgbox 0, "ActiveSheet release fails"
end if
if isfalse(COM_Succeeded(COM_Release(pXlBooks))) then
msgbox 0, "Workbooks release fails"
end if
if isfalse(COM_Succeeded(COM_Release(pXlApp))) then
msgbox 0, "Excel application release fails"
end if

Regards,
Roberto

Michael Clease
02-11-2007, 12:32
This is the error message I get.

RobertoBianchi
02-11-2007, 13:04
Yes, this is the error.
I changed the script in order to test if this is due to different process but I got same error.


uses "COM"

%NUMBER_OF_PARAMETERS = 3

dim pXlApp, pXlApp1, pXlBooks, pXlSheet AS DWORD
dim vParam(%NUMBER_OF_PARAMETERS), vRetVal AS VARIANT
dim hr, i, n AS LONG

pXlApp1 = COM_CreateObject("Excel.Application")

pXlApp = COM_GetActiveObject("Excel.Application")

if pXlApp = pXlApp1 then
msgbox 0, "Same handle" + $tab + pXlApp + $tab + pXlApp1
else
msgbox 0, "Different handle" + $tab + pXlApp + $tab + pXlApp1
end if

IF COM_Succeeded(hr) THEN
for i = 1 to %NUMBER_OF_PARAMETERS
COM_VariantInit(vParam(i))
next
vParam(1) = 1
if COM_Succeeded(COM_Execute(pXlApp, "Visible", %TB_DISPATCH_PROPERTYPUT, 1, vParam(1), 0)) then
msgbox 0, "Now Excel should be visible!"
COM_VariantInit(vRetVal)
if COM_Succeeded(COM_Execute(pXlApp, "Workbooks", %TB_DISPATCH_PROPERTYGET, 0, 0, vRetVal)) then
pXlBooks = vRetVal
if COM_Succeeded(COM_Execute(pXlBooks, "Add", %TB_DISPATCH_METHOD, 0, 0, 0)) then
msgbox 0, "A new workbook should be added!"
else
msgbox 0, "Add workbook fails"
end if
if COM_Succeeded(COM_Execute(pXlApp, "ActiveSheet", %TB_DISPATCH_PROPERTYGET, 0, 0, vRetVal)) then
pXlSheet = vRetVal
vParam(1) = "ThinBASIC"
if COM_Succeeded(COM_Execute(pXlSheet, "Name", %TB_DISPATCH_PROPERTYPUT, 1, vParam(1), 0)) then
msgbox 0, "ActiveSheet name should be changed!"
for i = 1 to 20
for n = 1 to 5
vParam(3) = i
vParam(2) = n
vParam(1) = "Hello"
COM_Execute(pXlSheet, "Cells", %TB_DISPATCH_PROPERTYPUT, %NUMBER_OF_PARAMETERS, vParam(1), 0)
next
next
if COM_Succeeded(COM_Execute(pXlApp, "Quit", %TB_DISPATCH_METHOD, 0, 0, 0)) then
msgbox 0, "Great!"
end if
end if
end if
end if
else
msgbox 0, "Visible fails"
end if
END IF

if isfalse(COM_Succeeded(COM_Release(pXlSheet))) then
msgbox 0, "ActiveSheet release fails"
end if
if isfalse(COM_Succeeded(COM_Release(pXlBooks))) then
msgbox 0, "Workbooks release fails"
end if
if isfalse(COM_Succeeded(COM_Release(pXlApp))) then
msgbox 0, "Excel application release fails"
end if

Michael Clease
02-11-2007, 14:45
If excel is running it fails but if it is not running it opens excel makes a workbook and fills it and than askes if you want ot save and closes.

Is this related http://support.microsoft.com/kb/266713.

RobertoBianchi
02-11-2007, 15:20
Hi Abraxas,


Is this related http://support.microsoft.com/kb/266713.

I do not think so because I don't use Active Template Library, in any case may be something related, I'll check again.

If Excel is running you got a same or different handle?

Thanks,
Roberto

Michael Clease
02-11-2007, 15:59
thats odd. It crashes on my work computer (office 2000) whether excel is running or not but works on my home pc (office 2003) as previous post.

on my work pc it reports different handles then crashes doesnt matter if excel is running or not.

will test my home system after work and post results.

hope that helps.

marcel
02-11-2007, 16:28
Hi,

I downloaded the dll as well and dropped it in the thinbasic lib folder. On my computer both scripts return the error. Different handle as well as other errors and warnings such as on GetIDsOfNames(). It does not matter if Excel is running or not.

I use Office2003 SP2 and a GenuineIntel processor.

Added:

What about http://support.microsoft.com/kb/238610/en-us and http://support.microsoft.com/kb/238975/en-us and http://support.microsoft.com/kb/196776/en-us

RobertoBianchi
02-11-2007, 17:49
Thanks, now I understand what happened, I returned IUnknown pointer instead of pointer to IDispatch interface for Automation.
I'll fix the module ASAP (at least I hope).

Regards,
Roberto

marcel
02-11-2007, 20:43
Roberto,

Take your time, don't hurry. :)

Kind regards

Marcel

RobertoBianchi
06-11-2007, 14:00
Marcel,

function COM_GetActiveObject() is now available.
Also I added the COM_SetErrorBehavior() and COM_GetErrorBehavior() in order to manage the behavior that the script has to follow in case of an error.
These are the behaviours:

%TB_ERROR_BEHAVIOR_DISPLAY_STOP display message and stop the script's execution (default)
%TB_ERROR_BEHAVIOR_DONT_DISPLAY don't display the error message
%TB_ERROR_BEHAVIOR_DONT_STOP don't stop the script's execution


You can combine %TB_ERROR_BEHAVIOR_DONT_DISPLAY with %TB_ERROR_BEHAVIOR_DONT_STOP.

Here is a script sample taht you can test with the attached module:


'----------------------------------------------------------------------------(')
USES "COM"

'----------------------------------------------------------------------------(')
%NUMBER_OF_PARAMETERS = 3

'----------------------------------------------------------------------------(')
DIM pXlApp, pXlBooks, pXlSheet AS DWORD
DIM vParam( %NUMBER_OF_PARAMETERS ), vRetVal AS VARIANT
DIM hr, i, n AS LONG

'----------------------------------------------------------------------------(')
pXlApp = COM_GetActiveObject( "Excel.Application" )

'----------------------------------------------------------------------------(')
if pXlApp = 0 then
msgbox 0, "Start a new Excel application"
pXlApp = COM_CREATEOBJECT( "Excel.Application" )
else
msgbox 0, "Attach to existing Excel application"
end if

'----------------------------------------------------------------------------(')
IF COM_SUCCEEDED( hr ) THEN
FOR i = 1 TO %NUMBER_OF_PARAMETERS
COM_VARIANTINIT( vParam( i ))
NEXT
vParam( 1 ) = 1
IF COM_SUCCEEDED( COM_EXECUTE( pXlApp, "Visible", %TB_DISPATCH_PROPERTYPUT, 1, vParam( 1 ), 0 )) THEN
MSGBOX 0, "Now Excel should be visible!"
COM_VARIANTINIT( vRetVal )
IF COM_SUCCEEDED( COM_EXECUTE( pXlApp, "Workbooks", %TB_DISPATCH_PROPERTYGET, 0, 0, vRetVal )) THEN
pXlBooks = vRetVal
IF COM_SUCCEEDED( COM_EXECUTE( pXlBooks, "Add", %TB_DISPATCH_METHOD, 0, 0, 0 )) THEN
MSGBOX 0, "A new workbook should be added!"
ELSE
MSGBOX 0, "Add workbook fails"
END IF
IF COM_SUCCEEDED( COM_EXECUTE( pXlApp, "ActiveSheet", %TB_DISPATCH_PROPERTYGET, 0, 0, vRetVal )) THEN
pXlSheet = vRetVal
vParam( 1 ) = "ThinBASIC"
IF COM_SUCCEEDED( COM_EXECUTE( pXlSheet, "Name", %TB_DISPATCH_PROPERTYPUT, 1, vParam( 1 ), 0 )) THEN
MSGBOX 0, "ActiveSheet name should be changed!"
FOR i = 1 TO 20
FOR n = 1 TO 5
vParam( 3 ) = i
vParam( 2 ) = n
vParam( 1 ) = "Hello"
COM_EXECUTE( pXlSheet, "Cells", %TB_DISPATCH_PROPERTYPUT, %NUMBER_OF_PARAMETERS, vParam( 1 ), 0 )
NEXT
NEXT
IF COM_SUCCEEDED( COM_EXECUTE( pXlApp, "Quit", %TB_DISPATCH_METHOD, 0, 0, 0 )) THEN
MSGBOX 0, "Great!"
END IF
END IF
END IF
END IF
ELSE
MSGBOX 0, "Visible fails"
END IF
END IF

'----------------------------------------------------------------------------(')
IF ISFALSE( COM_SUCCEEDED( COM_RELEASE( pXlSheet ))) THEN
MSGBOX 0, "ActiveSheet release fails"
END IF

'----------------------------------------------------------------------------(')
IF ISFALSE( COM_SUCCEEDED( COM_RELEASE( pXlBooks ))) THEN
MSGBOX 0, "Workbooks release fails"
END IF

'----------------------------------------------------------------------------(')
IF ISFALSE( COM_SUCCEEDED( COM_RELEASE( pXlApp ))) THEN
MSGBOX 0, "Excel application release fails"
END IF


Thank you very much and best regards,
Roberto

marcel
06-11-2007, 14:51
Hi Roberto,

Thank you very much! I tested the dll and it works like a charm. I'll test it with MSWord as well. I see that I will have to overcome the same window activation I had in the other language but that is no problem at all. I have to look if thinBasic can activate a window by its name from the window list. If word has several documents open all the windows are named after the open documents.

The best is that you now can manage the open ole_objects.  :)

Thank you very much!

Kind regards

Marcel

RobertoBianchi
06-11-2007, 15:19
Marcel,

the function that you need already exist, it's hWnd = Win_FindByTitle(WindowTitle [, FindMethod])

I'm sorry but I don't understand what you mean with
open ole_objectsdo you mean Open Office?

Ciao,
Roberto

ErosOlmi
06-11-2007, 15:33
Marcel,

Win_FindByTitle (http://www.thinbasic.com/public/products/thinBasic/help/html/win_findbytitle.htm) is in UI module. Hope it is what you are searching.
It can work with partial windows names, see help. But it will not work with child windows so if your MSWord uses different windows it will work fine other wise, old Word versions worked MDI. In this case Win_FindByTitle will not find child MDI windows.

Ciao
Eros

Michael Clease
06-11-2007, 15:41
Thanks for your work Roberto, I see a few applications for this coupled with the Comm module for the instruments I work with.

RobertoBianchi
06-11-2007, 15:50
Abraxas,

you are welcome!
Please let me know if you need somethings else, COM module is just sketched.

Bye,
Roberto

marcel
06-11-2007, 16:58
Marcel,

the function that you need already exist, it's hWnd = Win_FindByTitle(WindowTitle [, FindMethod])

I'm sorry but I don't understand what you mean with
open ole_objectsdo you mean Open Office?

Ciao,
Roberto

Hi Roberto,

Thanks for the win_findbytitle() function. This makes it a lot easyer.

No, I just mean instances of MSWord or Excel objects.

Kind Regards

Marcel

marcel
06-11-2007, 17:12
Marcel,

Win_FindByTitle (http://www.thinbasic.com/public/products/thinBasic/help/html/win_findbytitle.htm) is in UI module. Hope it is what you are searching.
It can work with partial windows names, see help. But it will not work with child windows so if your MSWord uses different windows it will work fine other wise, old Word versions worked MDI. In this case Win_FindByTitle will not find child MDI windows.

Ciao
Eros

Hi Eros,

Thanks for the information. I use MSOffice 2002/2003 and I think it uses child MDI windows but I don't know for sure. The function looks the same but I have to test it.

Kind regards,

Marcel

ErosOlmi
06-11-2007, 17:31
Marcel,

I've checked and Word 2003 uses multiple windows one for each document so WIN_FindByTitle will be able to find different open documents using window title. The same for Word 2000.

Ciao
Eros

marcel
06-11-2007, 17:40
Hi Eros,

That is what I call SERVICE, thanks.

Kind regards

Marcel

ErosOlmi
06-11-2007, 19:27
Thanks Marcel.
We try our best when we can.