# Install & Uninstall Tasks

Source: https://docs.interop.io/desktop/developers/seed-project/install-uninstall-tasks/index.html

## Overview

Available since io.Connect Desktop 10.0.4

**io.Connect Desktop** supports executing custom install and uninstall tasks via command-line triggers, allowing automated execution of scripts and commands during installation and uninstallation processes on both Windows and macOS.

Tasks can copy configuration, register protocols, download resources, clean up data, or back up preferences as part of installation and uninstallation.

## Execution Triggers

On Windows, Squirrel passes installation and uninstallation arguments to the platform automatically. For other deployment methods, including a macOS DMG, invoke the manual triggers from your installation or removal process.

The following command-line arguments trigger task execution:

| Argument | Platform | Description |
|----------|----------|-------------|
| `--post-install` | Cross-platform | Execute install tasks (manual trigger). |
| `--pre-uninstall` | Cross-platform | Execute uninstall tasks (manual trigger). |
| `--squirrel-install` | Windows | Initial installation (triggered by Squirrel installer). |
| `--squirrel-uninstall` | Windows | App uninstall (triggered by Squirrel installer). |
| `--squirrel-updated` | Windows | App update (triggered by Squirrel installer). |

The `--post-install` and `--pre-uninstall` flags can be used if you aren't using a Squirrel-based installer or if you want to manually test the install tasks.

> ⚠️ *Note that on Windows, Squirrel executes the install tasks after the initial installation and again after every update. Write install tasks that can run repeatedly without side effects (e.g., check whether a resource exists before creating it).*

To trigger the install tasks manually on Windows, execute:

```cmd
io-connect-desktop.exe --post-install
```

To trigger the install tasks manually on macOS, execute:

```cmd
open -a "io.Connect Desktop" --args --post-install
```

## Task Files

Install and uninstall tasks are defined in platform-specific JSON configuration files within the `/install` folder:

- `tasks.win32.json` defines Windows tasks.
- `tasks.darwin.json` defines macOS tasks.

The files are read from `<installation_location>/install` on both operating systems. The `<installation_location>` placeholder represents the executable folder on Windows and the app bundle `Contents` folder on macOS.

To add install tasks to your seed project, create the task files in the `/modifications/build/iocd/install` directory:

```text
modifications/
└── build/
    └── iocd/
        └── install/
            ├── tasks.win32.json  (Windows)
            └── tasks.darwin.json (macOS)
```

This ensures that the task files are included in your production build.

## Defining Tasks

The task files follow this structure:

```json
{
    "installTasks": [
        {
            "type": "run",
            "args": {
                "filename": "path/to/executable",
                "args": "command line arguments",
                "dir": "working/directory",
                "hide": true,
                "unattended": false,
                "exitCode0": "success",
                "exitCode1": "Custom error message",
                "exitCodeN": "success"
            }
        }
    ],
    "uninstallTasks": [
        {
            "type": "run",
            "args": { /* same structure */ }
        }
    ]
}
```

Each task has `"type": "run"` and an `"args"` object. The `"installTasks"` and `"uninstallTasks"` arrays contain the tasks for the corresponding operation.

The `"args"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"args"` | `string` | Command-line arguments to pass to the executable. The full command is passed to the system shell for parsing. |
| `"dir"` | `string` | Working directory for the process. Defaults to the install folder if not specified. Supports environment variables. |
| `"exitCode0"` to `"exitCodeN"` | `string` | Custom exit code handling. Use `"success"` to mark a non-zero exit code as success, or provide a custom error message. By default, exit code `0` is success and other exit codes are errors. |
| `"filename"` | `string` | **Required.** Path to the executable or script to run. Supports environment variable expansion (e.g., `%TEMP%`, `%APPDATA%`). |
| `"hide"` | `boolean` | Hide the process window (Windows only). Defaults to `false`. |
| `"unattended"` | `boolean` | Suppress error dialogs. If `true`, errors are logged only. Defaults to `false`. |

> ⚠️ *Note that tasks execute sequentially in the order defined. If a task fails with an exit code that isn't mapped to success, execution will stop and subsequent tasks won't run.*

## Examples

### Windows Batch Script

The following example demonstrates how to run installation and cleanup scripts on Windows. Place the scripts beside `tasks.win32.json` in the packaged `/install` folder:

```json
{
    "installTasks": [
        {
            "type": "run",
            "args": {
                "filename": "cmd.exe",
                "args": "/c copy-resources.bat",
                "hide": true,
                "exitCode0": "success",
                "exitCode1": "Error copying resources."
            }
        }
    ],
    "uninstallTasks": [
        {
            "type": "run",
            "args": {
                "filename": "cmd.exe",
                "args": "/c cleanup.bat",
                "hide": true
            }
        }
    ]
}
```

### macOS Shell Script

The following example demonstrates how to run shell scripts on macOS. Place `setup.sh` in the packaged `/install` folder. In this example, `cleanup.sh` must be available in the explicitly selected `/tmp` working directory:

```json
{
    "installTasks": [
        {
            "type": "run",
            "args": {
                "filename": "/bin/bash",
                "args": "setup.sh --silent",
                "hide": false
            }
        }
    ],
    "uninstallTasks": [
        {
            "type": "run",
            "args": {
                "filename": "/bin/bash",
                "args": "cleanup.sh",
                "dir": "/tmp"
            }
        }
    ]
}
```

### Custom Exit Code Mapping

You can map specific exit codes to success or custom error messages:

```json
{
    "installTasks": [
        {
            "type": "run",
            "args": {
                "filename": "installer.exe",
                "args": "--verify",
                "exitCode0": "success",
                "exitCode1": "Error validating the installation.",
                "exitCode2": "Error contacting server.",
                "exitCode3": "success",
                "exitCode4": "Network timeout - please retry."
            }
        }
    ]
}
```

In this example:
- Exit codes 0 and 3 are considered successful.
- Exit codes 1, 2, and 4 will show custom error messages.
- Any other exit code will show a default error message.

## Environment Variable Expansion

The `"filename"`, `"args"`, and `"dir"` properties support environment variable expansion using the `%VAR%` syntax. The following Windows example demonstrates paths in a task `"args"` object:

```json
{
    "args": {
        "filename": "%APPDATA%\\MyCompany\\install-script.bat",
        "dir": "%LOCALAPPDATA%\\MyCompany"
    }
}
```

### Platform Variables

The following environment variables are automatically set by **io.Connect Desktop** and available for use in all install tasks:

| Variable | Description | Example Value |
|----------|-------------|---------------|
| `IO_CD_EXE_NAME` | Executable file name. | `io-connect-desktop.exe` (Windows)<br/>`io-connect-desktop` (macOS) |
| `IO_CD_EXE_PATH` | Full path to the executable. *Available since io.Connect Desktop 10.4.* | `C:\Users\...\io-connect-desktop\app-10.0.4\io-connect-desktop.exe` (Windows)<br/>`/Applications/io.Connect Desktop.app/Contents/MacOS/io-connect-desktop` (macOS) |
| `IO_CD_ROOT_DIR` | Root installation directory. | `C:\Users\...\io-connect-desktop\app-10.0.4` (Windows)<br/>`/Applications/io.Connect Desktop.app/Contents` (macOS) |
| `IO_CD_INSTALL_DIR` | Directory containing install tasks. | `C:\Users\...\io-connect-desktop\app-10.0.4\install` (Windows)<br/>`/Applications/io.Connect Desktop.app/Contents/install` (macOS) |

## Troubleshooting

### Tasks Not Executing

- Verify that the `install/tasks.win32.json` (Windows) or `install/tasks.darwin.json` (macOS) file exists in the correct location.
- Check that the file contains valid JSON.
- Ensure the executable paths are correct and accessible.

### Failed Tasks

- Review the [install log](#troubleshooting-install_log) or the console output for error messages.
- Test the script manually to verify it works.
- Check file permissions (especially on macOS - scripts need execute permission).
- Verify environment variables are correctly expanded.

### Silent Installation Failures

- Ensure all tasks have `"unattended": true` to prevent error dialogs.
- Test each task individually to identify which one is failing.
- Consider adding custom exit code mappings for expected error conditions.

### Install Log

Available since io.Connect Desktop 10.4

**io.Connect Desktop** records the execution of install and uninstall tasks, including the task environment and the output and exit code of each task, in an `install.log` file:

- On Windows, in `%LocalAppData%/interop.io/io.Connect Desktop/UserData/install/install.log`.
- On macOS, in `~/Library/Application Support/interop.io/io.Connect Desktop/UserData/install/install.log`.

The location doesn't depend on the product name or the configured user data folder.
