Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

QUIT in EXE COM SERVER causes OLE exception

Status
Not open for further replies.

Olaf Doschke

Programmer
Oct 13, 2004
14,847
DE
First of all, you don't need QUIT in a DLL COM Server, as that's always running in the same thread as the caller you actually don't want to use that in such COM Servers.
And secondly, for EXE COM Servers, setting your reference to a COM Object to null does not only destroy the COM server but also exit the process of it.

Usually. You know, if you put together a few threads I started, that I work with Webrelated things in a VFP application and to do so free of side effects it turns out best to separate this into an own process uneffected by some timers and other application framework settings and general processing of things deadly for some aspects of my extensions. For example only that way I get a Webbrowser control and JS to behave correcly in regard to NewWindow2 events.

Anyway, to get to the question: In some yet not well understood cases oCOM = null does not end my COMServer EXE and I waste some Memory over the day with this. I got the glorious idea to simply do as Word and have a Quite method doing, well, QUIT, but that causes an exception. I could live with that and simply put the destruction of the COM object into TRY..CATCH in the client using it, but I wonder if that always was a thing or only in VFP9 or only in Win10 or some build of it, so if anyone would like to contribute to that knowledge, try this COMServer as EXEvutable and tell me whether you also get excpetions:

Code:
Define Class Application As Session OlePublic
   Procedure Alive() As String
      Return "Hello from PID "+Transform(_vfp.ProcessID)
   Endproc

   Procedure Quit() As VOID
      Quit
   Endproc

   Procedure Close() As VOID
      #Define WM_DESTROY 0x2
      #Define WM_CLOSE 0x10

      Declare Long SendMessage In "user32" Long @ HWnd,Long @ wMsg,Integer @ wParam,String @ Lparam
      SendMessage(_vfp.HWnd, WM_CLOSE, 0, 0)
      SendMessage(_vfp.HWnd, WM_DESTROY, 0, 0)
      SendMessage(_Screen.HWnd, WM_CLOSE, 0, 0)
      SendMessage(_Screen.HWnd, WM_DESTROY, 0, 0)
   Endproc

   Procedure Exit() As VOID
      Declare Long ExitProcess In "kernel32" Long exitcode
      ExitProcess(0)
   Endproc

   Procedure RefRelease() As VOID
      Sys(3098,This)
   Endproc

   Procedure Error()
      Lparameters nError, cMethod, nLine

      _Screen.Visible = .T.
      Messagebox(Textmerge("<<nError>>,<<cMethod>>,<<nLine>>"))
   Endproc
Enddefine

Store that as main.prg of a PJX you compile as EXE, run VFP as admin or finally register the exe with running your.exe /Regserver elevated.

Now play with it by trying the different ways to not only release the object variable but end the EXE in task manager. Simplest working way:

Code:
o = CreateObject("your.application") && name of class will depend on your PJX name
&& at this stage you will find your.exe in task manager, look out for PID given by:
? o.Alive()
o = null && EXE should vanish within task manager

I have no repro code where o=null does not also end the process, but assume that's the case, then there should be a way to quit it, too, shouldn't there?

Especially when you do...
Code:
o = CreateObject("your.application") && name of class will depend on your PJX name
&& at this stage you will find your.exe in task manager, look out for PID given by:
? o.Alive()
o.Quit()
...you'll get OLE exception 0 from ?:?.. in the client using the COMServer.

Nothing errors within the COM Server and also strange no other method but QUIT ends the object, you can call CLOSE() or EXIT and afterward call ALIVE() just fine.

I could live with the fact the client die variable becomes a zombie reference, as that should simply get a RELEASE or get out of scope anyway, but I'd like an exit without throwing an exepction I have to catch.

And I wonder if that was always the case with QUIT.

Bye, Olaf.

Olaf Doschke Software Engineering
 
I´m also getting "OLE lDispatch exception code 0 from ?: ?.." when doing o.Quit() (VFP9 Win10 latest Update)
 
Olaf,

I got the same results, except that Exit() reports an RPC call fail, the Windows process ends, but the client reference to it does not reflect its termination (leading to further errors until the reference is cleared).
 
Thanks, wibenji.

Atlopes, Ah, yes, I forgot that I first tried TerminateProcess with the ProcessID, which of course does not terminate the running process as it needs a Process Handle, not Id.

Yes, ExitProcess almost has the same effect as Quit, just a clearer exception message. So perhaps to start a timer doing the ExitProcess or Quit would be an idea:
Code:
Define Class Application As Session OlePublic
...
   Procedure Quit() As VOID
      _screen.addobject("quit","quittimer")
      _screen.quit.enabled = .T.
   Endproc
...
EndDefine

Define Class quittimer as Timer
   Interval = 1
   
   Procedure Timer()
      Quit
   EndProc 
EndDefine

That works. I still wonder whether you can't do a simpler end of the process from inside the COM Server by a client-side method call. Just as Word.Application.Quit() also manages to do.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top