IR
irwinrodriguez.dev
Back to docs

Quickstart

From zero to your first task running in another Visual FoxPro process, in five steps. Valid for FoxCore.Runtime 3.4.2.

Before you start

  • FoxCore.Runtime 3.4.2 installed and registered: the FoxCore.Runtime-Setup-3.4.2.exe installer does it, and ships verify.cmd to check. See Installation.
  • Visual FoxPro 9 SP2 registered as an automation server - it is the process that runs the tasks. Since 3.1.0 it can be another one: VFP Advanced, or your own .exe.
  • Your license, which is a JWT: you download it from the customer portal and pass it in code. See Licensing.

1. Check the engine is there

First of all, that the COM object gets created. If this fails it is the installation and not your code: none of the lines below will work.

Create the runtime and check it answers
LOCAL loRt
loRt = CREATEOBJECT("FoxCore.Runtime")
? loRt.Ping()                             && FoxCore.Runtime 3.4.2

2. Activate the license - and check the .T.

Activate() NEVER throws on an invalid license: it returns .F. and carries on. If you call it and do not look at what it returns, the engine starts anyway and you find out much later, when the first task is born Failed.

Activate the license and check the .T.
LOCAL lcJwt
lcJwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...."   && paste your JWT from the customer portal here

IF !loRt.Activate(lcJwt)
    MESSAGEBOX("La licencia de FoxCore no es valida.", 16, "FoxCore")
    RETURN
ENDIF
? loRt.IsLicensed                         && .T.

If you skip this step the lifecycle still works - Attach, Ping, Shutdown - but every task is born Failed with this exact message:

The message of a task without a license
FoxCore.Runtime: no hay una licencia valida para el producto 'FoxCore', asi que la tarea no se ejecuta. Activala por codigo al arrancar: loRt.Activate(<tu JWT>). Se consigue en https://irwinrodriguez.dev/products/foxcore

3. Attach, launch and pump

This is the whole cycle, and it is the same snippet that opens the API Reference. Attach() attaches the runtime TO THE THREAD you call it from. RunScript() returns the id straight away: the script is already running in another process. And Pump() is what serves the workers - without it, they just wait.

The whole cycle: activate, attach, launch and pump
LOCAL loRt, lcId

loRt = CREATEOBJECT("FoxCore.Runtime")
? loRt.Activate(lcJwt)                    && .T. -- your license, as a string
loRt.Attach(_VFP)                         && attaches the runtime TO THIS thread
loRt.MaxWorkers = 8

lcId = loRt.RunScript("RETURN 6 * 42", "la primera")   && the script runs in ANOTHER VFP process

DO WHILE !loRt.IsCompleted(lcId)
    loRt.Pump()                           && Pump() serves the workers; without it they just wait
    DOEVENTS
ENDDO

? loRt.GetState(lcId)                     && Completed
? loRt.GetResult(lcId)                    && 252
? loRt.GetError(lcId)                     && ""

loRt.Shutdown()                           && ALWAYS: it is what kills the workers
Pump() only from the Attach thread: Calling Pump() from another thread raises a controlled error. And inside a handler, a DOEVENTS reenters Pump(): it returns 0 doing nothing and without throwing, so it serves nobody. In a form, the place for Pump() is a Timer.

4. Collect the result

GetResult() returns what the script passed to RETURN. Until the task has finished successfully it returns .NULL., so you check the state first.

Collect the task's result or error
IF loRt.GetState(lcId) == "Completed"
    ? loRt.GetResult(lcId)                && what the script returned
ELSE
    ? loRt.GetError(lcId)                 && empty if it did not fail
ENDIF

5. Always close with Shutdown()

Shutdown() is what kills the worker processes. It is idempotent: calling it twice does no harm. If you do not call it, orphan vfp9.exe processes are left eating memory - and that is the most common way to break this.

Close the runtime and its workers
loRt.Shutdown()

And from here

  • Patterns - the large batch, progress with a bar and a cancel button, handlers, the blackboard, and how this breaks.
  • Examples - three complete programs you can copy and run.
  • API Reference - the six types and all their members, with what each returns when something fails.
Coming from the classic engine? If your code says CREATEOBJECT("FoxCore.FoxCoreClass"), that is the other engine - it still exists and is still supported, but it is not the one this page describes. The equivalence table is in "What no longer exists", at the end of the Reference.

Next: Advanced Patterns ->