Running a scheduled task in MoneyWorks

Sometimes you want to run a process in a MoneyWorks database on a schedule to happen whether people are logged into MoneyWorks or not. Usually this will involve connecting to a remote server and exchanging information one way or the other. You can do this using a combination of MWScript, the MoneyWorks client in command-line mode, and the built-in task scheduling system of your host operating system.

Let's assume you have already written the MWScript script to automate your process. You have a handler called YourHandler in a script named YourScript that does the job, and you want to run this automatically on a schedule.

Step 1: Make your script handler globally accessible

In your script, add the keyword public to your handler declaration

on YourHandler public
    // do stuff
end

This allows the handler to be called from outside of your script by prefixing the handler name with the script name: YourScript:YourHandler(). Importantly, the script can be invoked by MoneyWorks Gold or the moneyworks CLI tool from a terminal command line. Your script should not include any code that relies on a GUI.

Note: Don't use the script's Load handler. Load handlers run for every user every time they log in. Your special handler will only be executed according to your schedule (although you might also call it from a menu command to allow users to invoke it manually).

Activate your script and save the document

This ensure the script will be available to other clients when they log in (including the command line client you are about to employ...).

Step 2: Invoking the script from the command line

You can and should test out invoking your script from the command line in the Terminal app as shown below. Ideally, this would be done on the server using the specialised command line client that is part of the server installation. On Windows, this a a CUI executable, so you will be able to see the stdout output (and the exe can also be used in interactive mode, although you do not need that for the task at hand).

Command line client on the server

Mac:

/usr/local/bin/moneyworks -zve "=YourScript:YourHandler()" "moneyworks://folder:pass@127.0.0.1:6699?doc=user:pass@Document.moneyworks"

(/usr/local/bin/moneyworks is a symbolic link to the moneyworks CLI client which is inside the Datacentre Console app)

Windows Command Prompt:

"C:\Program Files\MoneyWorks Datacentre\moneyworks.exe" -zve "=YourScript:YourHandler()" "moneyworks://folder:pass@127.0.0.1:6699?doc=user:pass@Document.moneyworks"

Windows Powershell:

& "C:\Program Files\MoneyWorks Datacentre\moneyworks.exe" -zve "=YourScript:YourHandler()" "moneyworks://folder:pass@127.0.0.1:6699?doc=user:pass@Document.moneyworks"
  • The -z option tells MoneyWorks to load scripts when it logs into the file (this is not normally done in command-line mode). Note that this will load every script and execute its Load handler, so make sure that you do not have any scripts in the document that present UI in the Load handler (which you should never do anyway). Functions that install menu commands are OK, because they will do nothing when executed in command line mode.
  • The -v (verbose) option is not required, but while testing it will give you more output on the command line about what it going on
  • The -e option invokes the command supplied in the next argument
  • The argument beginning with = is shorthand for the command evaluate expr='...'
  • Finally the URL contains the location and login credentials of the document to be accessed. Use moneyworks://ssl/ if the server is using TLS encryption

This will connect to the document, execute the script handler, disconnect, and exit.

Since the command line client is part of the server installation, it will be updated whenever the server is updated.

Alternatively, if you do not have access to the server to run commands on it (perhaps you are using a MoneyWorks Now server), use the MoneyWorks Gold client on your own computer:

MoneyWorks Gold client

Mac:

/Applications/MoneyWorks\ Gold.app/Contents/MacOS/MoneyWorks\ Gold -ze "=YourScript:YourHandler()" "moneyworks://folder:pass@server:6699?doc=user:pass@Document.moneyworks"

Windows Command Prompt:

"C:\Program Files\MoneyWorks Gold\MoneyWorks Gold.exe" -ze "=YourScript:YourHandler()" "moneyworks://folder:pass@server:6699?doc=user:pass@Document.moneyworks"

Windows Powershell:

& "C:\Program Files\MoneyWorks Gold\MoneyWorks Gold.exe" -ze "=YourScript:YourHandler()" "moneyworks://folder:pass@server:6699?doc=user:pass@Document.moneyworks"

Note: If you have the 32-bit MoneyWorks Gold installed, it will be in Program Files (x86)

The only downside of using MoneyWorks Gold in command line mode like this, is that if the server is updated to a new version, you will need to intervene to ensure that the client is updated. Also note that while the -e option works with the MoneyWorks Gold GUI client on the command line on Windows, you have no access to stdin or stdout (due to limitations in the design of Windows), and therefore cannot use the interactive mode with the -i option.

Once you have verified that you can invoke your script from the commandline, it is time to set up a scheduled job.

Step 3: Running the command on a schedule

This is where the process diverges markedly on Mac vs Windows.

Windows

On Windows, use Task Scheduler to schedule tasks. Do this on a computer that will always be running (the server is ideal, using moneyworks.exe, but if that is not an option, some other computer with MoneyWorks Gold).

  1. Search for and open Task Scheduler
  2. Under Action, choose Create Task...
     

  3. Enter a Name, description, and choose a security option
     

    Since you want the task to run unattended, you will probably want to choose "Run whether user is logged on or not". In this case you will need to enter login credentials.
    If your script accesses a mapped network drive, be sure that it is mapped for the user you have selected to run as.

  4. In the Triggers tab, click New.. and specify the time schedule you want
     
    E.g. Begin the Task: On a schedule ; Daily — specify the start day and time and Recur every 1 days.
    You may want to use the Advanced settings to specify a different time interval such as "Repeat task every: 6 hours for a duration of: Indefinitely".
  5. In the Action tab, click New.. and specify the command
  6.  
    The Action will be "Start a program".
    The Program will be "C:\Program Files\MoneyWorks Datacentre\moneyworks.exe" or "C:\Program Files\MoneyWorks Gold\MoneyWorks Gold.exe" as appropriate.
    The Arguments will be as for the command line you tested above e.g.

    -ze "=YourScript:YourHandler()" "moneyworks://folder:pass@server:6699?doc=user:pass@Document.moneyworks"
  7. Click OK to save the task
     
    The task should show as "Ready" and will run according to your schedule. You can disable it by right-clicking it in the task list and choosing Disable.

Mac

If your script writes to the Mac's filesystem
The location that your script writes to has to be accessible. MoneyWorks restricts scripts to accessing safe paths specified in the application preferences. You can easily set the MoneyWorks scripting paths in MoneyWorks Gold for the case that you use MoneyWorks Gold for your scheduled automation. If you use the moneyworks command line client on the server, then you need to specify the location using defaults write

defaults write nz.co.cognito.moneyworks.cli safeScriptingPaths "/Users/Shared/Files"

In addition, macOS restricts programs from accessing any user's Documents or Downloads folder (or any network drive or externally attached drive) and will usually put up a permissions dialog the first time a program tries to access one of these locations. Difficulty: if you run the moneyworks command line tool from the Terminal, that permission will be applied to the Terminal app, not to the moneyworks command line tool, so granting the permission that way is not going to work when you run moneyworks on a schedule using launchd, and when you attempt it, the permissions dialog might not be shown to grant the privilege. With this in mind, the best advice is: Do not try to automate file writing to any user's Documents or Downloads folder, or any external or network drive. It is not worth the trouble. It is for this reason that the default scripted file creation location is in ~/Library/Application Support/Cognito/MoneyWorks Gold/Automation Files/. This is accessible by default.

Launchd

There is no built-in UI for scheduling tasks on the Mac. The standard method is to use launchd, which uses .plist files to specify the task parameters.

The easiest way to run a launchd task is as a launch agent in ~/Library/LaunchAgents. These will only run while you are logged in. On a server, after a reboot, you might not be logged in unless you set up autologin.

To always run, even with no-one logged into the computer, you can use a launch daemon in /Library/LaunchDaemons/. The property list for a launch daemon needs to be owned by root.

  1. In a text editor, create a property list for launchd that specifies how you want your job to run

This example will run once a day at 5am

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Disabled</key>
    <false/>
    <key>Label</key>
    <string>local.my.moneyworks.job</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/moneyworks</string>
        <string>-ze</string>
        <string>=YourScript:YourHandler()</string>
        <string>moneyworks://folder:pass@server:6699?doc=user:pass@Document.moneyworks</string>
    </array>
    <key>StandardErrorPath</key>
    <string>/tmp/local.my.moneyworks.job.log</string>
    <key>StandardOutPath</key>
    <string>/tmp/local.my.moneyworks.job.log</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>5</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>UserName</key>
    <string>your_username</string>
</dict>
</plist>

Note that you must

  • replace moneyworks://folder:pass@server:6699?doc=user:pass@Document.moneyworks with the actual URL to connect to your MoneyWorks document
  • replace YourScript:YourHandler() with the actual name of your handler
  • replace your_username with your username so that the job will run as your Mac user and pick up the preferences that you previously set for the nz.co.cognito.moneyworks.cli domain. This part of the plist is only required for a launch daemon. A launch agent will always run using your username. You can remove the key and its string value if you do not need them

For a launch agent that will run while you are logged into your Mac:

  1. Save the plain text file as (e.g.) local.my.moneyworks.job.plist in ~/Library/LaunchAgents (tip: If you cannot see the Library folder in your home folder, press Shift--. in the save dialog to toggle invisible folders)
  2. To load the job, use launchctl
     
    launchctl load -w ~/Library/LaunchAgents/local.my.moneyworks.job.plist

For a launch daemon that will run even while no-one is logged into the Mac:

  1. Copy the text
  2. Open Terminal and use sudo nano to create the plist file
     
    This is because the file needs to be owned by root
    sudo nano /Library/LaunchDaemons/local.my.moneyworks.job.plist
  3. Paste your xml that you copied
  4. Press ctrl-X to exit
  5. Press Y to save
  6. Press return
     
    Now you have your launchd property list in the required location, and it is owned by root, as required. If you need to edit it again later, go back to step 2
  7. To load the job, use launchctl
     
    sudo launchctl load -w /Library/LaunchDaemons/local.my.moneyworks.job.plist

Other resources

Since there is no UI for task scheduling on the Mac (Shortcuts.app can only do it in the iPhone version(!!)), if you regularly want to set up scheduled tasks, a third party app can make it easier to do. LaunchControl is a good option for this.

Posted in Uncategorized | Comments Off on Running a scheduled task in MoneyWorks