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:
Applicationlets you spawn a new Windows process in order to run an application.
Processlets you spawn a new process and return its standard output when it's finished.
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.
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
and in a batch file with
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:
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
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
⎕CMDcan result in some strange effects.
Execute is designed to get you around these obstacles.
Examples: the "Application" method
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"
Start a program and wait until it exits
This can be achieved with the default settings of the parameters you might specify:
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
in that application.
Start another program but don't wait for it
In order to achieve that we need to change one of the defaults. First create a namespace with all parameters and their default settings:
This creates a namespace with all parameters you may change. You can list the parameters available by calling the namespace's
cs.List timeoutAfter 0 dir hidden 0 wait 1
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.
Examples: the "Process" method
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.
Simple right argument
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/
Nested right argument
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.