Skip to main content
Version: v20 R4 BETA

SystemWorker

System workers allow the 4D code to call any external process (a shell command, PHP, etc.) on the same machine. System workers are called asynchronously. By using callbacks, 4D makes it possible to communicate both ways.

The SystemWorker class is available from the 4D class store.

Example

    // Windows example to get access to the ipconfig information
var $myWinWorker : 4D.SystemWorker
var $ipConfig : Text
$myWinWorker:= 4D.SystemWorker.new("ipconfig")
$ipConfig:=$myWinWorker.wait(1).response //timeout 1 second

// macOS example to change the permissions for a file on macOS
// chmod is the macOS command used to modify file access
var $myMacWorker : 4D.SystemWorker
$myMacWorker:= 4D.SystemWorker.new("chmod +x /folder/myfile.sh")

Summary

4D.SystemWorker.new ( commandLine : Text { ; options : Object } ) : 4D.SystemWorker    creates and returns a 4D.SystemWorker object that will execute the commandLine you passed as parameter to launch an external process
.closeInput()    closes the input stream (stdin) of the external process
.commandLine : Text    contains the command line passed as parameter to the new() function
.currentDirectory : 4D.Folder    contains the working directory in which the external process is executed
.dataType : Text    contains the type of the response body content
.encoding : Text    contains the encoding of the response body content
.errors : Collection    contains a collection of 4D errors in case of execution error(s) if any
.exitCode : Integer    contains the exit code returned by the external process
.hideWindow : Boolean    can be used to hide the window of the DOS console or the window of the launched executable (Windows only)
.pid : Integer    contains the process unique identifier of the external process at the system level
.postMessage( message : Text)
.postMessage( messageBLOB : Blob)
    allows you to write on the input stream (stdin) of the external process
.response : Text
.response : Blob
    contains the concatenation of all data returned once the request is terminated
.responseError : Text    contains the concatenation of all the errors returned, once the request is terminated
.terminate()    forces the SystemWorker to terminate its execution
.terminated : Boolean    contains true if the external process is terminated
.timeout : Integer    contains the duration in seconds before the external process will be killed if it is still alive
.wait( {timeout : Real} ) : 4D.SystemWorker    waits until the end of the SystemWorker execution or the specified timeout

4D.SystemWorker.new()

History
VersionChanges
v19 R4Added

4D.SystemWorker.new ( commandLine : Text { ; options : Object } ) : 4D.SystemWorker

ParameterTypeDescription
commandLineText->Command line to execute
optionsObject->Worker parameters
result4D.SystemWorker<-New asynchronous System worker or null if process not started

Description

The 4D.SystemWorker.new() function creates and returns a 4D.SystemWorker object that will execute the commandLine you passed as parameter to launch an external process.

The returned system worker object can be used to post messages to the worker and get the worker output.

If an error occurs during the creation of the proxy object, the function returns a null object and an error is thrown.

In the commandLine parameter, pass the full path of the application's file to be executed (posix syntax), as well as any required arguments, if necessary. If you pass only the application name, 4D will use the PATH environment variable to locate the executable.

Warning: This function can only launch executable applications; it cannot execute instructions that are part of the shell (command interpreter). For example, under Windows it is not possible to use this command to execute the dir instruction.

options Object

In the options parameter, pass an object that can contain the following properties:

PropertyTypeDefaultDescription
onResponseFormulaundefinedCallback for system worker messages. This callback is called once the complete response is received. It receives two objects as parameters (see below)
onDataFormulaundefinedCallback for system worker data. This callback is called each time the system worker receives data. It receives two objects as parameters (see below)
onDataErrorFormulaundefinedCallback for the external process errors (stderr of the external process). It receives two objects as parameters (see below)
onErrorFormulaundefinedCallback for execution errors, returned by the system worker in case of unusual runtime conditions (system errors). It receives two objects as parameters (see below)
onTerminateFormulaundefinedCallback when the external process is terminated. It receives two objects as parameters (see below)
timeoutNumberundefinedTime in seconds before the process is killed if it is still alive
dataTypeText"text"Type of the response body content. Possible values: "text" (default), "blob".
encodingText"UTF-8"Only if dataType="text". Encoding of the response body content. For the list of available values, see the CONVERT FROM TEXT command description
variablesObjectSets custom environment variables for the system worker. Syntax: variables.key=value, where key is the variable name and value its value. Values are converted into strings when possible. The value cannot contain a '='. If not defined, the system worker inherits from the 4D environment.
currentDirectoryFolderWorking directory in which the process is executed
hideWindowBooleantrue(Windows) Hide the application window (if possible) or the Windows console

All callback functions receive two object parameters. Their contents depend on the callback:

ParameterTypeonResponseonDataonDataErroronErroronTerminate
$param1ObjectSystemWorkerSystemWorkerSystemWorkerSystemWorkerSystemWorker
$param2.typeText"response""data""error""error""termination"
$param2.dataText or Blobreceived dataerror data

Here is the sequence of callback calls:

  1. onData and onDataError are executed one or several times
  2. if called, onError is executed once (stops the system worker processing)
  3. if no error occured, onResponse is executed once
  4. onTerminate is always executed

Returned value

The function returns a system worker object on which you can call functions and properties of the SystemWorker class.

Examples on Windows

  1. To open Notepad and open a specific document:
var $sw : 4D.SystemWorker
var $options : Object
$options:=New object
$options.hideWindow:= False

$sw:=4D.SystemWorker.new ("C:\\WINDOWS\\notepad.exe C:\\Docs\\new folder\\res.txt";$options)
  1. Run npm install in the console:
var $folder : 4D.Folder
var $options : Object
var $worker : 4D.SystemWorker

$folder:=Folder(fk database folder)
$options:=New object
$options.currentDirectory:=$folder
$options.hideWindow:=False

$worker:=4D.SystemWorker.new("cmd /c npm install";$options)

  1. To launch the Microsoft® Word® application and open a specific document:
$mydoc:="C:\\Program Files\\Microsoft Office\\Office15\\WINWORD.EXE C:\\Tempo\\output.txt"
var $sw : 4D.SystemWorker
$sw:=4D.SystemWorker.new($mydoc)
  1. To launch a command with the current directory and post a message:
var $param : Object
var $sys : 4D.SystemWorker

$param:=New object
$param.currentDirectory:=Folder(fk database folder)
$sys:=4D.SystemWorker.new("git commit -F -";$param)
$sys.postMessage("This is a postMessage")
$sys.closeInput()
  1. To allow the user to open an external document on Windows:
$docname:=Select document("";"*.*";"Choose the file to open";0)
If(OK=1)
var $sw : 4D.SystemWorker
$sw:=4D.SystemWorker.new("cmd.exe /C start \"\" \""+$docname+"\"")
End if

Examples on macOS

  1. Edit a text file (cat is the macOS command used to edit files). In this example, the full access path of the command is passed:

var $sw : 4D.SystemWorker
$sw:=4D.SystemWorker.new("/bin/cat /folder/myfile.txt")
$sw.wait() //synchronous execution

  1. To launch an independent "graphic" application, it is preferable to use the open system command (in this case, the code has the same effect as double-clicking the application):
var $sw : 4D.SystemWorker
$sw:=4D.SystemWorker.new ("open /Applications/Calculator.app")
  1. To get the contents of the "Users" folder (ls -l is the macOS equivalent of the dir command in DOS).
var $systemworker : 4D.SystemWorker
var $output : Text
var $errors : Collection

$systemworker:=4D.SystemWorker.new("/bin/ls -l /Users ")
$systemworker.wait(5)
$output:=$systemworker.response
$error:=$systemworker.errors

  1. Same command as above, but using a sample "Params" user class to show how to handle callback functions:

var $systemworker : 4D.SystemWorker
$systemworker:=4D.SystemWorker.new("/bin/ls -l /Users ";cs.Params.new())


// "Params" class

Class constructor
This.dataType:="text"
This.data:=""
This.dataError:=""

Function onResponse($systemWorker : Object)
This._createFile("onResponse"; $systemWorker.response)

Function onData($systemWorker : Object; $info : Object)
This.data+=$info.data
This._createFile("onData";this.data)

Function onDataError($systemWorker : Object; $info : Object)
This.dataError+=$info.data
This._createFile("onDataError";this.dataError)

Function onTerminate($systemWorker : Object)
var $textBody : Text
$textBody:="Response: "+$systemWorker.response
$textBody+="ResponseError: "+$systemWorker.responseError
This._createFile("onTerminate"; $textBody)

Function _createFile($title : Text; $textBody : Text)
TEXT TO DOCUMENT(Get 4D folder(Current resources folder)+$title+".txt"; $textBody)

.closeInput()

History
VersionChanges
v19 R4Added

.closeInput()

ParameterTypeDescription
Does not require any parameters

Description

The .closeInput() function closes the input stream (stdin) of the external process.

When the executable waits for all data to be received through postMessage(), .closeInput() is useful to indicate to the executable that data sending is finished and that it can proceed.

Example

// Create some data to gzip
var $input;$output : Blob
var $gzip : Text
TEXT TO BLOB("Hello, World!";$input)
$gzip:="\"C:\\Program Files (x86)\\GnuWin32\\bin\\gzip.exe\" "

// Create an asynchronous system worker
var $worker : 4D.SystemWorker
$worker:= 4D.SystemWorker.new($gzip;New object("dataType";"blob"))

// Send the compressed file on stdin.
$worker.postMessage($input)
// Note that we call closeInput() to indicate we're done.
// gzip (and most program waiting data from stdin) will wait for more data until the input is explicitely closed.
$worker.closeInput()
$worker.wait()

$output:=$worker.response

.commandLine

.commandLine : Text

Description

The .commandLine property contains the command line passed as parameter to the new() function.

This property is read-only.

.currentDirectory

.currentDirectory : 4D.Folder

Description

The .currentDirectory property contains the working directory in which the external process is executed.

.dataType

.dataType : Text

Description

The .dataType property contains the type of the response body content. Possible values : "text" or "blob".

This property is read-only.

.encoding

.encoding : Text

Description

The .encoding property contains the encoding of the response body content. This property is only available if the dataType is "text".

This property is read-only.

.errors

.errors : Collection

Description

The .errors property contains a collection of 4D errors in case of execution error(s) if any.

Each element of the collection is an object with the following properties:

PropertyTypeDescription
[].errorCodenumber4D error code
[].messagetextDescription of the 4D error
[ ].componentSignaturetextSignature of the internal component which returned the error

If no error occured, .errors is undefined.

.exitCode

.exitCode : Integer

Description

The .exitCode property contains the exit code returned by the external process. If the process did not terminate normaly, exitCode is undefined.

This property is read-only.

.hideWindow

.hideWindow : Boolean

Description

The .hideWindow property can be used to hide the window of the DOS console or the window of the launched executable (Windows only).

This property is read-write.

.pid

.pid : Integer

Description

The .pid property contains the process unique identifier of the external process at the system level.

This property is read-only.

.postMessage()

.postMessage( message : Text)
.postMessage( messageBLOB : Blob)

ParameterTypeDescription
messageText->Text to write on the input stream (stdin) of the external process
messageBLOBBlob->Bytes write on the input stream

Description

The .postMessage() function allows you to write on the input stream (stdin) of the external process. In the message parameter, pass the text to write in stdin.

The .postMessage() function also accepts a Blob type value in messageBLOB to pass in stdin, so that you can post binary data.

You can use the .dataType property of the options object to make response body return Blob values.

.response

.response : Text
.response : Blob

Description

The .response property contains the concatenation of all data returned once the request is terminated, i.e. the full message received from the process output.

The type of the message is defined according to the dataType attribute.

This property is read-only.

.responseError

.responseError : Text

Description

The .responseError property contains the concatenation of all the errors returned, once the request is terminated.

.terminate()

.terminate()

ParameterTypeDescription
Does not require any parameters

Description

The .terminate() function forces the SystemWorker to terminate its execution.

This function sends the instruction to terminate and give control back to the executing script.

.terminated

.terminated : Boolean

Description

The .terminated property contains true if the external process is terminated.

This property is read-only.

.timeout

.timeout : Integer

Description

The .timeout property contains the duration in seconds before the external process will be killed if it is still alive.

This property is read-only.

.wait()

History
VersionChanges

|v19 R4|Added|

.wait( {timeout : Real} ) : 4D.SystemWorker

ParameterTypeDescription
timeoutReal->Waiting time (in seconds)
Result4D.SystemWorker<-SystemWorker object

Description

The .wait() function waits until the end of the SystemWorker execution or the specified timeout.

In timeout, pass a value in seconds. The SystemWorker script will wait for the external process for the amount of time defined in the timeout parameter. If you omit the timeout parameter, the script execution will wait indefinitely.

Actually, .wait() waits until the end of processing of the onTerminate formula, except if the timeout is reached. If timeout is reached, the SystemWorker is not killed.

During a .wait() execution, callback functions are executed, especially callbacks from other events or from other SystemWorker instances. You can exit from a .wait() by calling terminate() from a callback.

This function returns the SystemWorker object.

This function is not necessary if you created the SystemWorker from a 4D worker process.