Execute
is a member of the APLTree library. The library is a collection of classes etc. that aim to support the Dyalog APL programmer. Search GitHub for "apltree" and you will find solutions to many every-day problems Dyalog APL programmers might have to solve.
Execute
provides two methods:
-
Application
lets you spawn a new Windows process in order to run an application. -
Process
lets you spawn a new process and return its standard output when it's finished.
Use Application
in order to run a program or a batch file when you are not in need for its output. A typical example is firing up another instance of Dyalog APL. Use Process
if you need the output of a certain program. A typical example would be the SubVersion "svn list" command.
Naturally Process
waits for the program to quit. Application
doesn't wait by default but you can change that default behaviour. If you do you will get the exit code of that application, if there is any. A return code can be returned by a Dyalog app with
⎕OFF 123
and in a batch file with
exit 123
Imagine you want run a foo.exe
which returns a 0 in case of success and a positive integer in case of an error.
Now in order to kick off an instance of foo.exe
one could simply execute:
⎕CMD 'foo.exe'
So why should someone bother to use Execute
instead? Well, there are a couple of good reasons:
-
You won't be able to catch the return code from
⎕CMD
. -
Although you can specify "hidden" as additional parameter an app executed this way will often pop up a window anway.
-
Firing up another instance of Dyalog with
⎕CMD
can result in some strange effects.
The class Execute
is designed to get you around these obstacles.
All examples assume that you have a variable path
in your workspace which points to the Dyalog EXE. A typical path would be:
path
"C:\Program Files (x86)\Dyalog\Dyalog APL 12.1 Unicode\dyalog.exe"
This can be achieved with the default settings of the parameters you might specify:
res←Execute.Application path
This starts another Dyalog APL. The method Execute.Application
waits until the started Dyalog APL exits.
⎕←Display'rc' 'processInfo' 'result' 'more',[⎕IO+0.1]res
┌→────────────────────────────────────┐
↓ ┌→─┐ │
│ │rc│ 0 │
│ └──┘ │
│ ┌→──────────┐ ┌→──────────────────┐ │
│ │processInfo│ │1228 1592 3292 6728│ │
│ └───────────┘ └~──────────────────┘ │
│ ┌→─────┐ │
│ │result│ 245 │
│ └──────┘ │
│ ┌→───┐ ┌⊖┐ │
│ │more│ │ │ │
│ └────┘ └─┘ │
└∊────────────────────────────────────┘
As you can see the "result" returned by the called application is 245. This is achieved by executing
⎕OFF 245
in that application.
In order to achieve that we need to change one of the defaults. First create a namespace with all parameters and their default settings:
cs←Execute.DefaultParms
This creates a namespace with all parameters you may change. You can list the parameters available by calling the namespace's List
method:
cs.List
timeoutAfter 0
dir
hidden 0
wait 1
Note that timeoutAfter←0
means no timeout at all while any positive integer is treated as number of seconds.
Now make your changes:
cs.wait←0
cs.hidden←1
cs.timeoutAfter←10
Now run the application:
cs Execute.Application path,' dlgtest.dws'
This starts Dyalog which then in turn loads the workspace DLGTEST
. Although the application writes to the session you won't see the session because of hidden
being 1. Note that this means that if the app crashes for any reason the user has no other means to finish the application than killing the process in the task manager.
The Process
method is designed to return whatever the called program is going to write to stdout. For that reason Process
always waits until "program" exits. The application returns three items:
- An indicator whether "program" could be started at all. 0 is okay while 1 means failure.
- Everything that was written to stdout by "program". This is either a simple string of a vector of strings.
- The exit code of the pogram called. If there is no exit code this is -1.
The following example would work in case the following preconditions are full-filled:
- You have a SubVersion client installed on your machine.
- You have access to the Internet.
- The path to the SubVersion executable is contained on the Windows environment variable "PATH".
path←'aplwiki.com/os/dyalog/IniFiles/branches/'
cmd←'svn list svn://',path
↑(1+⎕io)⊃#.Execute.Application cmd
RB-1.6/
RB-1.6.2/
RB-1.6.3/
RB-1.7.0/
RB-1.7.1/
Rather then specifying a simple right argument you can also pass a vector of strings. The first one is used in order to identify the program to be executed while the other items are used as input.
The following example works although it's by no means suggested to do this: The WinFile class offers a much better way so solve this. For example, if there are any non-ANSII-characters used in a file- or directory name, than you won't see them: they will show up as question marks. However, to demonstrate the usage of a vector of strings the example is fine.
Our goal is to start a command.com instance, execute the dir command and exit the command.com instance while returning an exit code 9:
cmd←'cmd' 'dir' 'exit 9'
↑(1+⎕io)⊃#.Execute.Application cmd
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
....
Note that you cannot specify input for a Dyalog session this way.
Many thanks to Peter-Michael Hager without whom this class wouldn't exist.