Mini-Launcher is an application launcher with the following features:
- DLL Injection
- Lua Scripting
- Splash Screen (optional)
- File Integrity
- Expanding Variables
- Verbatim Arguments
- Setting Environnement Variables
- Setting PCA Flags
π§ This software has an emphasis on being compatible with Linux/Proton.
π» This software is for my own personal use but feel free to use it.
File path to the json configuration file to use. Defaults to launcher.json
.
Path can be absolute or relative (to the current working dir)
Program will exit before starting the executable.
π‘ This flag can come in handy when testing Lua Script.
Display a message box with all the command line arguments and a short description.
{
bin: string,
cwd?: string,
args?: string,
env?: object,
hide?: bool,
shell?: bool,
wait?: bool,
script?: {
path: string,
fs?: bool,
net?: bool,
reg?: bool,
exec?: bool
},
addons?: []{
path: string,
required?: bool
},
integrity?: []{
sri: string,
path?: string,
size?: number,
signed?: bool
},
splash?: {
show: bool,
image: []string,
timeout?: number,
wait?: string
},
symlink?: []{
path: string,
dest: string
},
compatibility?: {
version?: string,
fullscreen?: bool,
admin?: bool,
invoker?: bool,
aware?: bool
},
prefix?: {
winver?: string,
dpi?: number,
overrides?: object
},
attrib?: []{
path: string,
hidden?: boolean,
readonly?: boolean
},
menu?: object
}
File path to the executable to launch.
Path can be absolute or relative (to the current working dir).
%VAR%
are expanded if any (see Expanding Variable for more details).
An option to override the current working dir of the executable to be launched.
This is equivalent to the "Start In" option of a Windows shortcut.
By default the parent directory of the executable is used.
Example: G:\METAPHOR\METAPHOR.exe
=> G:\METAPHOR\
Optional argument(s) to pass to the executable.
Argument(s) are passed "verbatim" ie: no quoting or escaping is done.
%VAR%
are expanded if any (see Expanding Variable for more details).
Add additional environment key-value pairs to the executable process.
Example:
{
"env": {
"GAMEPAD_LED": "BATTERYLVL"
}
}
%VAR%
in value are expanded if any (see Expanding Variable for more details).
When enabled, the executable will run without displaying a window, making it invisible to the user.
When enabled runs inside of a shell (%COMSPEC% ie cmd.exe
).
π‘Use the hide
option above to hide the shell.
When enabled, will wait for the executable to terminate before exiting.
Lua script to be run just before the executable (see Lua Scripting below for more details).
Originally this feature was for handling CD Key generation in old games.
See the ./example
directory for some examples.
-
path: string
Script file path can be absolute or relative (to the current working dir).
%VAR%
are expanded if any (see Expanding Variable for more details). -
fs, net, reg, exec ?: bool
(false)These flags act as a simple permissions system:
fs
: Filesystem operationnet
: Network requestreg
: Windows registryexec
: Shell command
You must explicitly grant access to these resources.
List of addons to inject to the executable process.
When required
is set to true
and if the injection failed, alert the user and kill the process.
Path can be absolute or relative (to the current working dir).
%VAR%
are expanded if any (see Expanding Variable for more details).
Example:
{
"addons": [
{ "path": "Launcher/opencnconline.dll", "required": true }
]
}
Important
This launcher does not support Wow64 injection so make sure the launcher, the executable and the addon are all the same arch (x86 or x64).
Check file(s) integrity before starting the executable.
-
sri: string
is a Subresource Integrity, algo supported aresha256, sha384, sha512
. -
path?: string
(executable path) File path, can be absolute or relative (to the current working dir). If no path is specified then the sri targets the executable path.
%VAR%
are expanded if any (see Expanding Variable for more details). -
size?: number
optional file size (in bytes), to accelerate sum comparison. -
signed?: bool
(false) When true, will check if the file is signed and trusted.
Display a splash screen until the executable process change the cursor or display a window. The splash screen should be a BMP file.
-
show: bool
(false) Wether to display the splash screen or not. -
image: []string
Splash screen filepath. When more than one, a splash screen is selected at random.
File path can be absolute or relative (to the current working dir).
%VAR%
are expanded if any (see Expanding Variable for more details). -
timeout?: number
(10 sec) Failsafe timeout in seconds.
There was no event dispatched under Linux/Proton on Wayland in my limited testing. -
wait?: string
("FOREGROUND") Which window event to wait for (case insensitive):FOREGROUND
: The foreground window has changed and is visible.WINDOW
: An hidden window is shown.CURSOR
: An hidden cursor is shown.
Creates folder symlink before starting the executable.
Path can be absolute or relative (to the current working dir).
%VAR%
are expanded if any (see Expanding Variable for more details).
π‘ Useful for savegames:
{
"symlink": [
{
"path": "%DOCUMENTS%/Telltale Games/The Walking Dead",
"dest": "%SAVEGAME%/The Walking Dead"
}
]
}
Caution
This requires elevated privileges ("Admin rights") or the SeCreateSymbolicLinkPrivilege
privilege.
Set Program Compatibility Assistant
(PCA) flags, this is equivalent to the right click > Properties > Compatibility tab
on Windows.
PCA flag(s) are set in HKCU/Software/Microsoft/Windows NT/CurrentVersion/AppCompatFlags/Layers
.
π§ This has no effect on application behavior under Wine/Proton
-
version?: string
Run the executable in compatibility mode for:WIN95
WIN98
WIN2000
WINXP
WINXPSP1
WINXPSP2
WINXPSP3
VISTARTM
VISTASP1
VISTASP2
WIN7RTM
WIN8RTM
-
fullscreen?: bool
Disable fullscreen optimizations. -
admin?: bool
Run the executable as an Administrator. -
invoker?: bool
Enforce running the executable as the invoker. -
aware?: bool
Override high DPI scaling behavior (Application).
NB: admin
and invoker
are mutually exclusive. If both are set admin
supersede invoker
.
π§ Linux Wine/Proton only.
Update current prefix settings.
-
winver?: string
Windows version. Accepted values are:win11
win10
win81
win8
win7
vista
winxp
-
dpi?: number
Scale factor: 96 (100%), 120 (125%), 144 (150%), 192 (200%) to 480 (500%). -
overrides?: object
key-value pairs of dll overrrides. Accepted values:native,builtin
builtin,native
native
builtin
Example:
{
"prefix": {
"winver": "win10",
"dpi": 96,
"overrides": {
"winmm": "native,builtin"
}
}
}
attrib?: []{path: string, hidden?: boolean = false, readonly?: boolean = false}
(none)
Set file(s) attributes: read only and/or hidden.
Path can be absolute or relative (to the current working dir).
%VAR%
are expanded if any (see Expanding Variable for more details).
Show a very simple button menu where each key/value pair is a button label and its corresponding override config file.
Example:
{
"menu": {
"Mass Effect": "me.json",
"Mass Effect 2": "me2.json",
"Mass Effect 3": "me3.json"
}
}
Path can be absolute or relative (to the current working dir).
%VAR%
in the path are expanded if any (see Expanding Variable for more details).
π‘ You can point an entry to the default config file.
If empty, the default is assumed ie: the value of --config string
which defaults to launcher.json
Example:
{
"binary": "bin/bg3_dx11.exe"
"menu": {
"Baldurs Gate 3": "",
"Baldurs Gate 3 (Vulkan)": "vulkan.json"
}
}
List of variables that will get expanded:
%APPDATA%
%LOCALAPPDATA%
%PROGRAMDATA%
%DESKTOP%
%DOCUMENTS%
%MUSIC%
%PICTURES%
%VIDEOS%
%DOWNLOAD%
%SAVEGAME%
%HOMEDIR%
,%USERPROFILE%
%PUBLIC%
%SYSTEMDIR%
%TEMP%
,%TMP%
%CURRENTDIR%
: Current working dir of the mini-launcher%BINDIR%
: Dir where the mini-launcher is located at%USERNAME%
%LANGCODE%
: User's language as ISO 639 language code (ex:en
,fr
,de
)%LANGUAGE%
: User's language in English (ex:english
,french
,german
)%SCREENWIDTH%
,%XRES%
: Current primary display horizontal resolution (DPI Aware)%SCREENHEIGHT%
,%YRES%
: Current primary display vertical resolution (DPI Aware)%SCREENREFRESH%
: Current primary display refresh rate
Very simple scripting engine powered by yuin/gopher-lua.
See the ./example
directory for some examples.
- Lua 5.1
- Libraries:
- Package
- Basic
- Table
- String
- Math
- Coroutine
Some standard libraries are not enabled by design.
The followings modules are exposed to the Lua VM, I might add more later on.
Suspends the execution of the Lua engine until the time-out interval elapses (interval is in milliseconds).
log(any, ...)
warn(any, ...)
error(any, ...)
Convenience methods to print value or array with timestamp and log level. Values are colored depending on their type.
π‘ print()
is an alias to console.log()
find(table, func) any
some(table, func) bool
includes(table, any) bool
Convenience methods to search array Lua table.
Example:
local arr = {1, 2, 3, 4, 5}
Array.find(arr, function(x) return x > 3 end)
Array.includes(arr, 3)
local arr = {
{foo = "bar", value = 1},
{foo = "baz", value = 2}
}
Array.find(arr, function(x) return x.foo == "bar" end)
Array.some(arr, function(x) return x.foo == "baz" end)
Failure is a custom type (userdata) that represents an "error object" with an associated error code and message. This provides a structured way to handle error.
-
code?: string
("ERR_UNKNOWN") Error code. -
message?: string
("An unknown error occurred") Error message.
π‘ Failure
has a __tostring
metamethod. If not invoked automatically, you can explicitly call it using tostring(Failure)
Example:
local err = Failure("ERR_NOT_FOUND", "The requested item was not found")
print(err.code) -- "ERR_NOT_FOUND"
print(err.message) -- "The requested item was not found"
print(err) -- "[ERR_NOT_FOUND]: The requested item was not found"
local value, err = Foo()
if err and err.code == "ERR_UNKNOWN" then
error(err.message) -- Raise an error "An unknown error occurred"
-- or
error(tostring(err))
end
This is a module to read and write from/to the registry.
Requires the
reg
permission.
local regedit = require("regedit")
KeyExists(root: string, path: string) bool
ListAllSubkeys(root: string, path: string) []string
ListAllValues(root: string, path: string) []string
QueryValueType(root: string, path: string, key: string) string
QueryStringValue(root: string, path: string, key: string) string
//REG_SZ & REG_EXPAND_SZQueryMultiStringValue(root: string, path: string, key: string) []string
//REG_MULTI_SZQueryBinaryValue(root: string, path: string, key: string) string
//REG_BINARYQueryIntegerValue(root: string, path: string, key: string) string
//REG_DWORD & REG_QWORDWriteKey(root: string, path: string)
DeleteKey(root: string, path: string)
WriteStringValue(root: string, path: string, key: string, value: string)
//REG_SZWriteExpandStringValue(root: string, path: string, key: string, value: string)
//REG_EXPAND_SZWriteMultiStringValue(root: string, path: string, key: string, value: []string)
//REG_MULTI_SZWriteBinaryValue(root: string, path: string, key: string, value: string)
//REG_BINARYWriteDwordValue(root: string, path: string, key: string, value: string)
//REG_DWORDWriteQwordValue(root: string, path: string, key: string, value: string)
//REG_QWORDDeleteKeyValue(root: string, path: string, key: string)
βοΈ root
key accepted values are "HKCR", "HKCU", "HKLM", "HKU" or "HKCC"
.
π‘For the default key @
use key = ""
%VAR%
in WriteStringValue(..., value)
are expanded if any (see Expanding Variable for more details).
NB: REG_DWORD
& REG_QWORD
are represented as string due to floating-point precision limits, if you need to perform arithmetic on them in Lua use tonumber()
.
This is a module to generate random things.
local random = require("random")
AlphaNumString(length: number) string
UserPID() number
Generate a random alpha numeric string of specified length.
Picks a random PID from the user-owned processes.
This is a module to read and write text data from/to file.
Requires the
fs
permission.
local file = require("file")
Write(filename: string, data: string, format?: string = "utf8") Failure
Read(filename: string, format?: string = "utf8") string, Failure
Remove(path: string) Failure
Info(filename: string) object, Failure
Glob(root: string, pattern: string, options?: { recursive?: false, absolute?: false }) []string, Failure
Basename(path: string, suffix?: bool = true) string
Encoding format:
utf8
utf8sig
utf16le
windows1252
%VAR%
in filename
/ root
are expanded if any (see Expanding Variable for more details).
Overwrite text data with specified format encoding (default to utf8).
Create target parent dir if doesn't exist.
File is created if doesn't exist.
Read text data as specified format encoding (default to utf8).
Delete file or directory and any children it contains at the given path.
Retrieves information for the specified path.
Time information are represented as Unix epoch time (seconds).
If the target is a file this will also include the file version information (if any) and whether the file is signed and trusted or not.
{
size: number,
time: {
modification: number,
creation?: number,
access?: number
},
version?: {
major: number,
minor: number,
build: number,
revision: number
},
signed?: bool
}
Glob(root: string, pattern: string, options?: { recursive?: false, absolute?: false }) []string, Failure
Returns the names of all files matching pattern. The pattern syntax is the same as in Go path/filepath Match.
With the addition that, to return only directories the pattern should end with /
.
Returns the last element of path. When suffix
is false
the file extension is removed.
Example:
file.Basename("/foo/bar/quux.html");
-- Returns: "quux.html"
file.Basename("/foo/bar/quux.html", false);
-- Returns: "quux"
This is a module to parse/stringify config files.
local JSON = require("config/json")
local TOML = require("config/toml")
local INI = require("config/ini")
local YAML = require("config/yaml")
local XML = require("config/xml")
JSON
Parse(data: string) table, Failure
Stringify(data: table, pretty?: bool = true) string, Failure
TOML
Parse(data: string) table, Failure
Stringify(data: table) string, Failure
INI
Parse(data: string, options?: table) table
Stringify(data: table, options?: table) string
YAML
Parse(data: string) table, Failure
Stringify(data: table) string, Failure
XML
Parse(data: string) table, Failure
Stringify(data: table, pretty?: bool = true) string, Failure
Parse options:
filter?: []string (none)
Section filterglobal?: bool (true)
Include global sectionunquote?: bool (true)
Unquote string (starting/ending with"
or'
)boolean?: bool (true)
String to boolean type conversionnumber?: bool (true)
String to number type conversion (same rules as JavaScript's JSON.parse())
Stringify options:
whitespace?: bool (true)
add space between delimiter=
blankLine?: bool (false)
add empty line between sectionsquote?: bool (false)
quote string with"
eol?: string (system)
Either\n
or\r\n
This is a module to do http request.
Requires the
net
permission.
local http = require("http")
Fetch(url: string, options?: {method?: string, headers?: table, body?: string }) {status, body, headers}, Failure
Download(url: string, destDir: string) string, Failure
Fetch(url: string, options?: {method?: string, headers?: table, body?: string }) {status, body, headers}, Failure
A Fetch like API.
Example:
local http = require("http")
local JSON = require("config/json")
local repo = "xan105/Mini-Launcher"
local url = "https://api.github.com/repos/" .. repo .. "/releases/latest"
local res, err = http.Fetch(url, {
method = "GET",
headers = {
["Accept"] = "application/vnd.github.v3+json",
["User-Agent"] = "Chrome/"
}
})
if err then
console.error(err)
end
local github, err = JSON.Parse(res.body)
if err then
console.error(err)
end
local latestRelease = github["tag_name"]
Download a file. Filename is determined by the Content-Disposition
header.
Create target parent dir if doesn't exist.
Overwrite existing file.
Return the downloaded file path.
%VAR%
in destDir
are expanded if any (see Expanding Variable for more details).
Example:
local http = require("http")
local filepath, err = http.Download("http://.../foo.bar", "%DOWNLOAD%")
if err then
console.error(err)
else
console.log("downloaded: " .. filepath)
end
This is a module to decompress archive file.
Requires the
fs
permission.
local archive = require("archive")
Unzip(filePath: string, destDir: string, excludeList?: []string) Failure
Un7z(filePath: string, destDir: string, excludeList?: []string) Failure
Extract .zip
/ 7.z
archive to destDir
. Overwriting existing files.
%VAR%
are expanded if any (see Expanding Variable for more details).
This is a module to get info about the current user.
local user = require("user")
name: string
: User nameadmin: bool
: has elevated rights ?language: string
: User's language in English (ex:english
,french
,german
)locale
: User's language as ISO 639code: string
: language code (ex:en
,fr
,de
)region: string
: language region (ex:US
,BE
,DE
)
This is a module to get info about the current display mode.
local video = require("video")
Current() { width: number (px), height: number (px), hz: number, scale: number (%)}, Failure
This is a module to get info about the current Mini-Launcher process.
local process = require("process")
platform: string
: operating system target (GOOS)arch: string
: architecture target (GOARCH)pid: number
: process idCwd() string
: process current working dirExecPath() string
: process absolute pathnameOn(event: string, callback: function)
: register callback function to be run for specified event
Events
will-quit
: Fired when process is about to terminate.
This is a module to execute shell command.
Requires the
exec
permission.
local shell = require("shell")
Run(command: string) {stdout: string, stderr: string}, Failure
Spawns a shell then execute the command within that shell (ComSpec).
This is a module to handle time conversion.
local time = require("time")
Current() number
: Current Unix timeHumanizeDuration(seconds: number) string
ToUnix(datetime: string, format?: string = "ISO8601") number, Failure
ToIso8601(datetime: number) string
NB: ToUnix()
supported formats are:
- "ISO8601"
- "YYYY-MM-DD"
- "YYYY/MM/DD"
- "YYYY_MM_DD"
- "DD-MM-YYYY"
- "DD/MM/YYYY"
- "MM-DD-YYYY"
- "MM/DD/YYYY"
- "YYYY-MM-DD HH:MM:SS"
- "YYYY/MM/DD HH:MM:SS"
- Golang v1.24.1
- go-winres installed in
%PATH%
env var for win32 manifest & cie
Run build.cmd
on Windows
Run build.sh
on Linux
Output files are located in ./build/${platform}/${config}