Can you keep a server around after it's been released?

I received a question from a reader:

I decided to extend my VPF9SP1 application to support OLE Automation like MS Office. I'd like to enable user (through code, i.e. VBA macro in Excel) to instantiate my app, create a new form, fill-in some data and display the form on screen and let the user decide what to do next.

Unfortunately, after releasing reference variable in client code, a form disappeared and my application ended.

I understand, that I should increment RefCount to keep my app running, but how can I do that in VFP code?

Is there any way in VFP to access IDispatch interface of COM server itself?

Try the code below. It creates a runtime VFP COM server (like “Excel.Application”, but a little simpler) that displays a form.

It then offers 2 MessageBoxes in a row. Try answering No to each the first time running the code. That shows the default behavior. When the server is released from the client, the refcount is decremented to none, the object is released and the form disappears.

Answering Yes to either MessageBox demonstrates how the refcount can be modified in two ways: one from the client and one from the server.

Both use SYS(3097) - Add Reference to Object. The one from the client is quite simple. From the server itself, we pass in the same Server reference variable oSrv and bump the refcount on that.

See also:

Managing Object Lifetimes Through Reference Counting

To make the runtime VFP screen invisible at runtime, see Special Terms for Configuration Files

More about VFP COM servers: Blogs get 300 hits per hour: Visual FoxPro can count.

IF !FILE("testxx.exe")

      TEXT TO myprog noshow

      DEFINE CLASS c1 as session olepublic

      proc MyDoCmd(cCmd as string,p2 as Variant,p3 as Variant,p4 as Variant,p5 as Variant) helpstring 'Execute a command'

      &cCmd

      proc MyEval(cExpr as string,p2 as Variant,p3 as Variant,p4 as Variant,p5 as Variant) helpstring 'Evaluate an expression'

      RETURN &cExpr

      ENDDEFINE

      ENDTEXT

      STRTOFILE(myprog,"testxx.prg")

      BUILD PROJECT testxx FROM testxx

      BUILD EXE testxx FROM testxx

ENDIF

PUBLIC oSrv

oSrv=CREATEOBJECT("testxx.c1")

oSrv.MyDoCmd("_screen.Visible=1")

oSrv.MyDoCmd("_screen.Height = 400")

oSrv.MyDoCmd("_screen.Width = 400")

?oSrv.MyEval("_vfp.fullname")

oSrv.MyDoCmd("public oForm")

oSrv.MyDoCmd("oForm = CREATEOBJECT('form')")

oSrv.MyDoCmd("oForm.Visible=1")

IF MESSAGEBOX("AddRef the server from the client?",4) = 6 && IDYES from foxpro.h

      ?"The client is making an additional AddRef on the server"

      ?SYS(3097,oSrv) && AddRef the server ref count

ENDIF

IF MESSAGEBOX("AddRef the server?",4) = 6 && IDYES from foxpro.h

      ?"The server is making an additional AddRef on itself"

      oSrv.MyDoCmd("PUBLIC oMe") && create a var to store a self ref

      oSrv.MyDoCmd("oMe = p2",oSrv) && set that var to self

      ?oSrv.MyEval("SYS(3097,oMe)") && AddRef the server ref count

ENDIF

oSrv=0 && release the server