DotFix Script — Custom Scripting Engine
DotFix Script is the built-in automation language of DotFix NiceProtect. It lets you run your own scripts immediately before and after the protection stage — to prepare input files, edit the PE header, strip unwanted resources, patch the protected binary, compute checksums, sign it, or kick off your installer build — without leaving the tool.
Overview
A DotFix Script is plain text, interpreted line by line at runtime. Each line is one command followed by comma‑separated parameters. There is no separate compile step you manage: you write the script, and the engine reads it from top to bottom, executing one command per line.
NiceProtect can invoke a script at two points in a protection job:
- Pre‑protection — before the file is processed. Use it to stage source files, clean previous output, generate inputs, or read settings.
- Post‑protection — after the protected binary is written. Use it to patch the output, adjust PE headers, hash or sign the result, copy it to a release folder, or notify the user.
The file being produced is exposed to the script through the predefined register @output. Commands that read or write a binary without an explicit path operate on this output file by default.
- The number of script lines is not limited.
- Empty lines are skipped.
- Lines beginning with
;,#, or!are comments. - An unknown command is reported as an error; the script continues with the next line.
- Lines starting with
GPSare treated as obfuscated and decrypted automatically, so you can ship scripts whose contents are not easily readable.
0 if it finished with no errors, or 1 if one or more errors were recorded — so a faulty script can fail your build pipeline.
Syntax
One command per line. The command name is separated from its parameters by the first space; parameters are separated by commas. A command takes up to ten parameters. Command names are case‑insensitive, and leading spaces in a parameter are trimmed.
To include commas or spaces literally, wrap a parameter in double quotes; a doubled quote ("") inside produces one literal quote. The escape \n is converted to a line break.
Registers & macros
A register is a named slot holding a string. You create one simply by writing to it; most commands take the destination register name as their last parameter. Prefix a name with @ anywhere in a parameter to substitute its current value before the command runs.
Several predefined registers are filled in automatically:
| Register | Value |
|---|---|
@windows | Windows directory, with trailing backslash. |
@temp | User temp directory, with trailing backslash. |
@current | Directory of the running NiceProtect executable. |
@output | Full path of the output file for the current job. |
@crlf | A carriage‑return + line‑feed pair. |
How numbers are read
Numbers are decimal by default throughout the engine. A value written with a 0x (or $) prefix is hexadecimal; anything else is decimal. Every command that produces a number writes it in decimal, so the result of one operation feeds straight into the next.
Calculation and byte layout are two separate ideas. Use calc to compute a value, then pack to turn it into a fixed‑width little‑ or big‑endian byte string for writing into a file.
putcode and the result of getcode are hex byte strings (for example 90909090), not decimal quantities.
Conditions (the IF modifier)
Any command can be made conditional by appending an IF clause as its last parameter. If the condition is false, the command is skipped.
A condition is one or more comparisons of the form value OP value:
| Operator | Meaning | Comparison |
|---|---|---|
= | equal | string |
^ | not equal (also !=, <>) | string |
> | greater than | numeric |
< | less than | numeric |
>= | greater or equal | numeric |
<= | less or equal | numeric |
The relational operators compare numerically, using the 0x/decimal rule above. Comparisons can be joined with AND and OR, evaluated left to right.
IF clause must not contain spaces. To compare text with spaces, store it in a register and compare the register, or test emptiness with length.
Commands — variables & math
Math commands accept decimal or hex input and write a decimal result.
Stores value verbatim into destReg.
Evaluates an arithmetic expression with + - * / and parentheses; numbers may be decimal or hex. Result is decimal, or an unpadded hex string when the third parameter is hex.
Encodes value as a fixed‑width hex byte string in little‑ or big‑endian order, ready for putcode.
Decodes a hex byte string back into a decimal number.
Addition, subtraction, multiplication, integer division. Inputs decimal or hex; decimal result. div reports an error on a zero or missing divisor.
Encodes value as a little‑endian 4‑byte hex string. Retained for compatibility; pack value, dword, le, dest is the clearer equivalent.
Commands — strings
Joins a and b.
Stores the length of value (decimal).
Extracts count characters from source starting at position start (1‑based).
Builds a string of count repetitions of the first character of char.
Convert a character to its two‑digit hex code and back.
Stores a random byte as a two‑digit hex string.
Commands — labels & jumps
Declares a jump target. Labels are resolved before execution, so you can jump forward or backward.
Transfers execution to a label, optionally only when a condition holds.
Stops the script immediately.
Commands — files
Creates a directory, including missing parents.
Copies a file. A trailing $ on a path expands to the application directory.
Deletes a file.
Appends text as a new line to file, creating it if needed.
Reads the entire output file into a register.
Stores the size of file in bytes (decimal).
Commands — binary & PE editing
These operate on the output file and understand the Windows PE format. Addresses and offsets accept decimal or hex on input and are returned in decimal.
Writes a sequence of bytes (hex string) at a file offset. putcode 0x1000, 90909090 writes four NOP bytes.
Reads length bytes from offset and stores them as a hex string.
Resolves the original entry point: raw file offset and RVA (both decimal).
Sets the PE entry point to the given RVA.
Stores the PE image base address (decimal).
Reads or writes the OEM identifier string in the DOS stub (up to 29 characters).
Appends a new PE section with the given name and size (decimal), returning its raw offset and RVA, and updates the image size.
Sets the characteristics flags on the file's sections (use 0x for a hex bitmask).
XOR‑encrypts a region of code at the given RVA with a random key, writes it back, and returns a ready‑to‑use decryptor stub (hex) in the register.
Commands — Registry / INI / XML
Across all three stores the convention is the same: set writes, get reads.
Writes a value. Root is one of HKCR HKCU HKLM HKU HKPD HKCC HKDD; Type is REG_DWORD or a string type.
Reads a value, with an optional default if it is missing.
Writes a value to an INI file.
Reads a value, or an empty string if absent.
Writes Value as the text of the node addressed by XPath (for example /root/item). Creates the file and any missing elements of a simple path automatically; saved as UTF‑8 without a BOM.
Reads the text of the node, or an empty string if the file or node is absent. Loading detects the file's actual encoding, so files from other tools load reliably.
Commands — dialogs & console
Shows a message box and stores the numeric button result.
Prompts for a line of text.
Places text on the clipboard.
A console is available for interactive output. It adapts to how the protector was launched: in the console build console.load reuses the existing console; in the GUI build it creates a window, and console.unload closes only what it created. The close button and Ctrl‑C are disabled for a created console so the user cannot terminate the protector by closing it. The status command always writes to the protection log, so console commands are optional.
Attach a console / write a line / read a line.
Set text colour / set mode flags / detach the console.
Commands — system
Runs an external command or console application, waits for it to finish, and stores its exit code (decimal). On a start failure it records an error and stores -1.
Runs a program or opens a file or URL through the shell, without waiting.
Reads an environment variable into a register.
Computes the MD5 (32 hex chars) or SHA‑256 (64 hex chars) hash of a file.
Loads a DLL, calls an exported function with three integer arguments, and stores the numeric return value.
Wait for a number of milliseconds / play a WAV file.
Writes a diagnostic line to the NiceProtect status bar (and the console, if attached). The main way to report progress from a script.
Examples
Copy the protected file into a release folder
Stamp a checksum and sign the protected binary
Compute an address and patch bytes
Errors & diagnostics
Errors are collected during the run and printed to the status bar when it finishes; each begins with ! and names the failing command and line. A failed command does not stop the script — the next line still runs. Use status with a simple convention such as [PASS], [FAIL], and [INFO] prefixes to make results easy to scan, and check the run's return code (0/1) from your build system.
Change language: English German Russian