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


 

Comments (2)

  1. Janusz Czudek says:

    First method works only from VFP client, as it calls SYS(3097,oSrv) – so it is not REALLY a solution.

    Second method is not very elegant, as we need to pass reference to COM server itself: oSrv.SomeMethod(oSrv). We don’t need do such things automating Excel, do we?

    It would be perfect, if we could increment refcount internaly in COM server code without a need for getting reference from client code. Or better – if VFP could increment its refcount whenever form is showed on screen (as VB6 does). Maybe in Sedna? 😉

    (In you sample we don’t need to call SYS(3097) – storing object reference in public variable is sufficient)

    Thank you.

  2. Calvin_Hsia says:

    Try using the _VFP.Objects collection:

    ?oSrv.MyEval("SYS(3097,_vfp.Objects(2))")