Fixing Moses 3D to Cloos Robot Program Export via QTI API

Home
Photography
Projects
About me
Robots
Publications
Friends' pages:
Chris
Jeff
John
Minu
Raeed
Email me:
alex AT joni.ro


Share

If you work with Moses 3D simulation software and Cloos welding robots, you might encounter an issue where exporting robot programs (.L files) fails silently or throws initialization errors.

Here is a breakdown of why this happens and how to fix it by creating a custom API interceptor wrapper.

The Problem

When exporting a program (e.g., Rohr1), Moses creates a CSV file containing parameters and writes a configuration file named QTIApi.CFG inside C:\Cloos\QTI\:

   1;C:\Moses\Konfiguration\CLOOS\DRASS\ROB\CFG
   2;C:\Moses\MSTEILE\PROGD\Rohr1
   3;DE

Moses then triggers the Cloos command-line tool QTIAPI.exe with a single command:

   QTIAPI.exe /CMD 5 Rohr1

Instead of generating Rohr1.L, the export fails. Checking the official Cloos log at %ProgramData%\Cloos Schweisstechnik\QTI\QTIAPI.log reveals the following error:

   4 /CMD 5 Rohr1  QTI could not be initialized

Root Cause

QTIAPI.exe treats every execution as a stateless, isolated session. When invoked directly with /CMD 5, it does not automatically parse QTIApi.CFG on its own.

Before running conversion commands, QTIAPI.exe expects two mandatory setup calls during runtime:

Because Moses calls QTIAPI.exe /CMD 5 directly without passing the /cfg flags first, QTIAPI.exe fails to initialize.

The Solution: A C# API Interceptor

To resolve this, rename the original executable to QTIAPI_real.exe and replace QTIAPI.exe with a lightweight custom C# wrapper.

When Moses calls QTIAPI.exe /CMD 5 Rohr1, the wrapper intercepts the call and executes the full sequence:

       Moses Export
            │
            ▼
       QTIAPI.exe (Custom Wrapper)
            │
            ├── 1. Intercepts original parameters
            ├── 2. Reads and parses QTIApi.CFG
            ├── 3. Executes: QTIAPI_real.exe /cfg 1 "C:\Moses\Konfiguration\..."
            ├── 4. Executes: QTIAPI_real.exe /cfg 2 "C:\Moses\MSTEILE\..."
            └── 5. Executes: QTIAPI_real.exe /CMD 5 Rohr1
            │
            ▼
       QTIAPI_real.exe  ──► Successfully generates Rohr1.L 

Implementation Steps

Step 1: Rename the Original Binary
Navigate to C:\Cloos\QTI\ and rename QTIAPI.exe to QTIAPI_real.exe.

Step 2: Compile the Wrapper Executable
Open PowerShell on your system and run the following script to compile the wrapper directly into C:\Cloos\QTI\QTIAPI.exe:

$code = @'
using System;
using System.Diagnostics;
using System.IO;

class Program {
    static void Main(string[] args) {
        string logFile = @"C:\Cloos\QTI\execution_trap.log";
        string realExe = @"C:\Cloos\QTI\QTIAPI_real.exe";
        string cfgFile = @"C:\Cloos\QTI\QTIApi.CFG";

        // Step 1: Log intercepted call
        string originalArgs = string.Join(" ", args);
        File.AppendAllText(logFile, "[" + DateTime.Now.ToString() + "] Intercepted call: " + originalArgs + "\r\n");

        if (!File.Exists(realExe)) {
            File.AppendAllText(logFile, "[" + DateTime.Now.ToString() + "] ERROR: QTIAPI_real.exe not found.\r\n");
            return;
        }

        // Step 2: Read and parse QTIApi.CFG
        if (File.Exists(cfgFile)) {
            string[] lines = File.ReadAllLines(cfgFile);
            foreach (string line in lines) {
                if (string.IsNullOrWhiteSpace(line)) continue;

                string[] parts = line.Split(';');
                if (parts.Length >= 2) {
                    string id = parts[0].Trim();
                    string path = parts[1].Trim();

                    // Step 3 & 4: Issue /cfg 1 and /cfg 2 prior to command execution
                    if (id == "1" || id == "2") {
                        string cfgArgs = "/cfg " + id + " \"" + path + "\"";
                        ExecuteRealExe(realExe, cfgArgs, logFile);
                    }
                }
            }
        } else {
            File.AppendAllText(logFile, "[" + DateTime.Now.ToString() + "] WARNING: QTIApi.CFG not found at " + cfgFile + "\r\n");
        }

        // Step 5: Execute original command
        ExecuteRealExe(realExe, originalArgs, logFile);
    }

    static void ExecuteRealExe(string exePath, string arguments, string logFile) {
        File.AppendAllText(logFile, "[" + DateTime.Now.ToString() + "] Executing: QTIAPI_real.exe " + arguments + "\r\n");

        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.FileName = exePath;
        startInfo.Arguments = arguments;
        startInfo.UseShellExecute = false;

        using (Process process = Process.Start(startInfo)) {
            process.WaitForExit();
        }
    }
}
'@

Add-Type -TypeDefinition $code -OutputAssembly "C:\Cloos\QTI\QTIAPI.exe" -OutputType ConsoleApplication

Verification

      [11.09.2026 17:42:58] Intercepted call: /CMD 5 Rohr1
      [11.09.2026 17:42:58] Executing: QTIAPI_real.exe /cfg 1 "C:\Moses\Konfiguration\CLOOS\DRASS\ROB\CFG"
      [11.09.2026 17:43:00] Executing: QTIAPI_real.exe /cfg 2 "C:\Moses\MSTEILE\PROGD\Rohr1"
      [11.09.2026 17:43:01] Executing: QTIAPI_real.exe /CMD 5 Rohr1


0 /CMD 5 Rohr1

The target .L parameter file will now be successfully created in your project output folder.




[æ]