A small, scriptable wrapper around the Aras Batch Loader to run data loads from the command line and in automation.
Subscribers receive the Batch Loader tool (GUI) and the BatchLoaderCmd.exe CLI utility as part of the Aras Innovator product. This repository is a sample script that wraps BatchLoaderCmd.exe to help automate repeatable, CLI‑first data loads and integrate them into pipelines. It is not a replacement for the product utilities.
This script makes Batch Loader easier to use in a CLI‑only workflow:
- Keep CLI connection settings separate from the UI’s BatchLoader config.
- Run from any folder while pointing to the BatchLoader runtime (DLLs resolve).
- Discover matching AML templates for each data file automatically.
- Process files in a predictable order so base items load before relationships.
- Write a per‑file log for fast troubleshooting.
- Python 3.10+ (3.11+ recommended).
- Access to the BatchLoader runtime folder (contains
BatchLoaderCmd.exeand DLLs). - Network access and permissions to load data into your Innovator instance.
- Verify Python is on PATH
python --version
# or
py --version- Copy the runtime config (one‑time)
python .\batchloader.py --init-config --init-from-runtime --bl-dir "C:\\path\\to\\BatchLoader" --bl-config .\CLIBatchLoaderConfig.xml- Edit the CLI config
- Open
CLIBatchLoaderConfig.xmland setserver,db,user,password. - Ensure
<loader_dir>points to the BatchLoader runtime folder. Adjustdelimiterandfirst_rowif needed.
- Run the loader
# Using loader_dir embedded in CLIBatchLoaderConfig.xml
python .\batchloader.py
# OR override at runtime
python .\batchloader.py --bl-dir "C:\\innovator\\Release 35 CD Image\\BatchLoader"- Review logs in
./logs
That’s it for a first run. For more details, see Install / Setup and Conventions.
- Download Python 3.11+
- Run the installer and check “Add python.exe to PATH”.
- Verify in a new PowerShell window:
python --version
# or
py --versionDependencies: this project uses only the Python standard library (no pip installs). A virtual environment is optional:
python -m venv .venv
.\.venv\Scripts\Activate.ps1Obtain the BatchLoader runtime folder that contains BatchLoaderCmd.exe and all DLLs (shipped with Aras Innovator). Note its path, for example:
C:\\innovator\\Release 35 CD Image\\BatchLoader
Clone this repo (or copy batchloader.py + CLIBatchLoaderConfig.xml into a working folder). The repo includes sample data in ./data.
Example layout:
.
├─ batchloader.py # Python CLI wrapper
├─ CLIBatchLoaderConfig.xml # CLI-only config
├─ data/ # Sample data + templates
└─ logs/ # Created on first run
Important: Your BatchLoader runtime folder may live outside this repo. Point to it via --bl-dir or <loader_dir> inside CLIBatchLoaderConfig.xml. DLLs must be in the same folder as BatchLoaderCmd.exe.
If you already have a working runtime BatchLoaderConfig.xml (used by the UI), clone it into a clean CLI config and inject the loader path:
python .\batchloader.py --init-config --init-from-runtime --bl-dir "C:\\path\\to\\BatchLoader" --bl-config .\CLIBatchLoaderConfig.xmlThis copies BatchLoaderConfig.xml from the runtime folder and adds a <loader_dir> element so future runs don’t need --bl-dir.
After copying, open CLIBatchLoaderConfig.xml and edit the connection settings (server, db, user, password). The script reads connection info from this file and runs will fail without valid values.
Open CLIBatchLoaderConfig.xml and set values:
<BatchLoaderConfig>
<server>https://YOUR-INNOVATOR-URL</server>
<db>YOUR_DATABASE_NAME</db>
<user>admin</user>
<password>innovatorpassword123</password>
<max_processes>1</max_processes>
<threads>1</threads>
<lines_per_process>250</lines_per_process>
<delimiter>\t</delimiter>
<encoding>utf-8</encoding>
<first_row>2</first_row>
<log_level>3</log_level>
<loader_dir>..\..\..\BatchLoader</loader_dir>
</BatchLoaderConfig>Guidance:
server: your Innovator site URL (without the trailing/Server).db: the SQL Server database name for your environment.user/password: an Innovator account with permissions to load data.first_row: 2 if files include a header row; 1 if not.- Headerless rule: when
first_row = 1, column 1 must be the GUID used for deletes (required header name with headers:id).
- Headerless rule: when
delimiter:\t,,, or|to match your file format.loader_dir: folder that containsBatchLoaderCmd.exeand DLLs.
Windows is the primary and most tested target. Linux/macOS can work via Wine:
- Install Wine; ensure
wineis on PATH. - BatchLoader is a Windows .NET app. Install the .NET Framework in Wine. Wine‑Mono alone may not suffice.
- Use
--bl-dirpointing to the BatchLoader runtime folder accessible to Wine; prefer absolute paths.
Examples:
# Load data
python3 ./batchloader.py --bl-dir "/innovator/CDImage35Release/BatchLoader"
# Delete data
python3 ./batchloader.py --delete --bl-dir "/innovator/CDImage35Release/BatchLoader"
# Clean failed files
python3 ./batchloader.py --clean-failedData formatting and ordering are critical for correct results.
See CONVENTIONS.md for data and template organization, load order, and CSV/TSV format expectations.
--bl-dir: Runtime folder withBatchLoaderCmd.exeand DLLs.--bl-config: CLI config path (default./CLIBatchLoaderConfig.xml).--data-dir: Data directory (default./data).--templates-dir: Optional separate templates directory.--logs-dir: Where to write logs (default./logs; deletes →./logs/delete, retries →./logs/retry).--retry[--retry-dir]: Replay.failedfiles.--delete[--delete-templates-dir]: Reverse delete using generated templates (default delete-templates dir:./templates_delete).--clean-failed: Remove all.failedfiles.--init-config --init-from-runtime: Create a CLI config from the runtime.
See all options: python .\batchloader.py -h.
# Using loader_dir embedded in CLIBatchLoaderConfig.xml
python .\batchloader.py
# OR override at runtime (if <loader_dir> is not set)
python .\batchloader.py --bl-dir "C:\\innovator\\Release 35 CD Image\\BatchLoader"- Each run writes a per‑file log into
--logs-dir, e.g.,logs/001-User.log. - If
BatchLoaderCmd.exereturns non‑zero, the script prints:-> non-zero exit (<code>); check <logfile>. - BatchLoader writes a
<stem>.failedfile containing rows that did not load.
Fast retries
If a run generates .failed row files, they’re written alongside your data using the data file’s stem (no .txt). Example: data\001-Parts_TopAndAssemblies.failed.
# Looks in ./data for *.failed and replays them
python .\batchloader.py --retry
# If your .failed files are in a different location:
python .\batchloader.py --retry --retry-dir .\some\other\folder
# Provide a separate templates directory if templates aren’t in /data
python .\batchloader.py --retry --templates-dir .\templatesNotes
- Searches for
.failedin--retry-dir(if provided) or--data-dir(default:./data). - Retry file name matches the original data file’s stem.
- Template resolution during retries:
--templates-dir/<stem>.xml, elsedata/<stem>_Template.xml. - Logs go to
./logs/retry/<stem>.retry.log(e.g.,logs/retry/001-Parts_TopAndAssemblies.retry.log).
The --delete flag provides a straightforward way to remove what you just loaded:
# Delete everything in reverse order (relationships first, then items)
python .\batchloader.py --delete
# Specify custom delete templates directory
python .\batchloader.py --delete --delete-templates-dir .\custom_delete_templatesHow it works
- Processes files in reverse order (relationships before items to respect dependencies).
- Auto‑generates delete templates based on your existing insert templates.
- For relationships: uses the relationship ID from your data files (
id). - For items: uses the Item ID from your data files (
id).
- For relationships: uses the relationship ID from your data files (
- Logs all deletions to
./logs/delete/. - Generated delete templates are written to
./templates_deleteby default (override with--delete-templates-dir). - Ensure data files satisfy the ID column requirements in
CONVENTIONS.mdso delete mode can identify rows by ID.
Required ID column for deletes
- Items: include an
idcolumn with the Item’s GUID. With headers, the column can be anywhere; without headers, place the GUID in column 1. - Relationships: include an
idcolumn with the relationship row GUID. With headers, the column can be anywhere; without headers, place the GUID in column 1.
Remove all *.failed files from your data directory:
# Remove failed files and exit
python .\batchloader.py --clean-failed
# Remove from custom data directory
python .\batchloader.py --clean-failed --data-dir .\custom_data- Processes only
*.txtdata files (and*.failedin retry mode). - The script does not enforce a specific AML action; whatever your template specifies (
add,merge, etc.) is used.--deleteis a separate mode that generates delete templates. - Non-Windows environments require Wine installed and on PATH.