WebExeBuilder Documentation

Instance Mode Control

Category: Advanced

Description

Control whether your application runs as a single instance (reusing the existing window) or allows multiple instances (new window per launch). This can be configured at three levels with a clear priority order.

Priority Order

Priority Mechanism Effect
1 (highest) --NEW-WINDOW command-line argument Always opens a new instance
2 instance-mode.txt preference file Overrides the project setting
3 (lowest) Project OneInstance setting in WebExeBuilder Default behavior

Project Setting (Default)

In WebExeBuilder, the Single Instance checkbox in project settings controls the default behavior:

  • Enabled (OneInstance = True): Only one instance runs. Subsequent launches pass their file argument to the existing instance via the tab bar.
  • Disabled (OneInstance = False): Each launch opens a new window.

User Preference File

Your application can override the project setting at runtime by writing a preference file. This allows end users to choose their preferred behavior from within your app's settings.

File location:

%LOCALAPPDATA%\ezWareLab\WebExeBuilder\{APP-GUID}\storage\instance-mode.txt

Valid values:

  • single — Enforce single instance (even if project has OneInstance = False)
  • multi — Allow multiple instances (even if project has OneInstance = True)

If the file doesn't exist or contains an invalid value, the project setting is used as the fallback.

Writing the Preference

// Set single-instance mode (open files in existing window)
const storageDir = await web.storage.getDir();
await web.files.writeTextFile({
    filePath: storageDir + 'instance-mode.txt',
    contents: 'single'
});
// Set multi-instance mode (open files in new windows)
const storageDir = await web.storage.getDir();
await web.files.writeTextFile({
    filePath: storageDir + 'instance-mode.txt',
    contents: 'multi'
});

The preference takes effect on the next launch — it cannot change the behavior of the currently running instance.

--NEW-WINDOW Argument

The --NEW-WINDOW command-line argument forces a new instance regardless of any other setting. This is useful for "Open in New Window" menu actions.

// Open the current file in a new window
const f = getCurrentFile(); // your app logic
if (f && f.path) {
    await web.shell.execute({
        filePath: await web.directory.getAppExeDir() + 'MyApp.exe',
        arguments: '--NEW-WINDOW "' + f.path + '"'
    });
}

When --NEW-WINDOW is present:

  • The mutex check is skipped entirely
  • A new instance starts with its own window
  • The file argument (if any) is opened in the new instance

Single Instance Behavior

When single-instance mode is active and a second launch occurs:

  1. The new process detects the existing instance via a system mutex
  2. If a file argument is present, it's sent to the existing instance via WM_COPYDATA
  3. The existing instance opens the file (or switches to it if already open)
  4. The existing instance is brought to the foreground
  5. The new process exits immediately

Implementation Example

Settings UI for instance mode

// In your app's settings, let the user choose behavior
async function saveInstancePreference(mode) {
    // mode = 'single' or 'multi'
    const storageDir = await web.storage.getDir();
    await web.files.writeTextFile({
        filePath: storageDir + 'instance-mode.txt',
        contents: mode
    });
}

// Read current preference
async function getInstancePreference() {
    try {
        const storageDir = await web.storage.getDir();
        const content = await web.files.readTextFile({
            filePath: storageDir + 'instance-mode.txt'
        });
        return content.trim(); // 'single' or 'multi'
    } catch (_) {
        return ''; // No preference set, using project default
    }
}

"Open in New Window" menu action

async function openInNewWindow(filePath) {
    const exeDir = await web.directory.getAppExeDir();
    const exeName = 'MyApp.exe'; // your exe name
    await web.shell.execute({
        filePath: exeDir + exeName,
        arguments: '--NEW-WINDOW "' + filePath + '"'
    });
}

Notes

  • The preference file is read before the application window is created — changes take effect on next launch
  • --NEW-WINDOW always wins, regardless of preference file or project setting
  • --STYLE and --STYLE-FILE arguments (used for theme changes) also skip the single-instance check to allow restarts
  • The /CLOSE argument sends a close message to the existing instance without opening a new one
  • When in single-instance mode, the existing window is brought to the foreground using AttachThreadInput for reliable activation even when behind other windows