Short description
🧩 LispLoader v1.0.000 is an AutoCAD and Civil 3D .NET startup loader that reads LoaderConfig.txt and safely processes configured LSP VLX FAS and DLL program files.
📄 One configured file failing does not intentionally stop the remaining load sequence and all results are written to the AutoCAD command line and a rolling disk log.
⚙️ The plugin starts its configured load sequence immediately when the compiled LispLoader DLL is loaded into AutoCAD.
Command:
Startup action: NETLOAD LispLoader.dll
Configuration file: LoaderConfig.txt
Log file: LispLoader.log
Description:
🧩 LispLoader v1.0.000 is an AutoCAD and Civil 3D .NET startup loader that reads LoaderConfig.txt and safely processes configured LSP VLX FAS and DLL program files.
📄 One configured file failing does not intentionally stop the remaining load sequence and all results are written to the AutoCAD command line and a rolling disk log.
⚙️ The plugin starts its configured load sequence immediately when the compiled LispLoader DLL is loaded into AutoCAD.
Helper function: (if any)
Functionalities:
✅ Configuration driven loading – uses LoaderConfig.txt as the source list.
✅ LSP loading – supports AutoLISP source files.
✅ VLX loading – supports Visual LISP executable files.
✅ FAS loading – supports compiled AutoLISP files.
✅ DLL loading – loads .NET assemblies with Assembly.LoadFrom and ExtensionLoader.
✅ Relative and absolute paths – accepts both path types in the configuration.
✅ Failure isolation – continues the loop when individual files are missing or return a handled failure.
✅ Command line logging – reports loading progress inside AutoCAD.
✅ Rolling disk log – writes LispLoader.log and rotates it at 5 MB.
✅ Version banner – prints version and build timestamp when the plugin initializes.
Result:
🎯 LispLoader v1.0.000 provides the described AutoCAD or Civil 3D workflow.
📌 The generated SEO description is based on the supplied source code or project files.
Images, animations etc.
XAML code:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:Autodesk.Windows;assembly=AdWindows">
<src:RibbonToolTip x:Key="LispsLoader">
<src:RibbonToolTip.ExpandedContent>
<StackPanel>
<TextBlock Background="AntiqueWhite" TextAlignment="Left">
<Bold>Function Syntax: LispsLoader</Bold>
<LineBreak/>
<Bold>Version: 1.0 Date: 11.08.2026 3:19:48PM</Bold>
<LineBreak/>
<Bold>Version: 1.0 Date: 11.08.2026 3:19:52PM</Bold>
<LineBreak/>
<Hyperlink>N/A</Hyperlink>
<Bold><Run Foreground="DodgerBlue">Description</Run></Bold><LineBreak/>
<Run Foreground="White">🧩 LispLoader v1.0.000 is an AutoCAD and Civil 3D .NET startup loader that reads LoaderConfig.txt and safely processes configured LSP VLX FAS and DLL program files.</Run><LineBreak/>
<Run Foreground="White">📄 One configured file failing does not intentionally stop the remaining load sequence and all results are written to the AutoCAD command line and a rolling disk log.</Run><LineBreak/>
<Run Foreground="White">⚙️ The plugin starts its configured load sequence immediately when the compiled LispLoader DLL is loaded into AutoCAD.</Run><LineBreak/>
<LineBreak/>
<Bold><Run Foreground="DodgerBlue">Function Syntax</Run></Bold><LineBreak/>
<Run Foreground="White">Startup action: </Run><Bold><Run Foreground="Orange">NETLOAD LispLoader.dll</Run></Bold><LineBreak/>
<Run Foreground="White">Configuration file: </Run><Bold><Run Foreground="Orange">LoaderConfig.txt</Run></Bold><LineBreak/>
<Run Foreground="White">Log file: </Run><Bold><Run Foreground="Orange">LispLoader.log</Run></Bold><LineBreak/>
<LineBreak/>
<Bold><Run Foreground="LimeGreen">Primary Workflow</Run></Bold><LineBreak/>
<Run Foreground="White">1. NETLOAD LispLoader.dll into AutoCAD.</Run><LineBreak/>
<Run Foreground="White">2. AutoCAD calls the plugin Initialize method.</Run><LineBreak/>
<Run Foreground="White">3. The plugin prints the version and build timestamp.</Run><LineBreak/>
<Run Foreground="White">4. LoaderConfig.txt is read and blank or commented lines are ignored.</Run><LineBreak/>
<Run Foreground="White">5. Configured files are resolved and processed one by one.</Run><LineBreak/>
<Run Foreground="White">6. LSP VLX and FAS files are sent to the active AutoCAD document as load expressions.</Run><LineBreak/>
<Run Foreground="White">7. DLL files are loaded into the AppDomain and registered through AutoCAD ExtensionLoader.</Run><LineBreak/>
<Run Foreground="White">8. A final OK FAILED and SKIPPED summary is written to the log.</Run><LineBreak/>
<LineBreak/>
<Bold><Run Foreground="LimeGreen">Functionalities</Run></Bold><LineBreak/>
<Run Foreground="White">✅ </Run><Bold><Run Foreground="LimeGreen">Configuration driven loading</Run></Bold><Run Foreground="White"> - uses LoaderConfig.txt as the source list.</Run><LineBreak/>
<Run Foreground="White">✅ </Run><Bold><Run Foreground="LimeGreen">LSP loading</Run></Bold><Run Foreground="White"> - supports AutoLISP source files.</Run><LineBreak/>
<Run Foreground="White">✅ </Run><Bold><Run Foreground="LimeGreen">VLX loading</Run></Bold><Run Foreground="White"> - supports Visual LISP executable files.</Run><LineBreak/>
<Run Foreground="White">✅ </Run><Bold><Run Foreground="LimeGreen">FAS loading</Run></Bold><Run Foreground="White"> - supports compiled AutoLISP files.</Run><LineBreak/>
<Run Foreground="White">✅ </Run><Bold><Run Foreground="LimeGreen">DLL loading</Run></Bold><Run Foreground="White"> - loads .NET assemblies with Assembly.LoadFrom and ExtensionLoader.</Run><LineBreak/>
<Run Foreground="White">✅ </Run><Bold><Run Foreground="LimeGreen">Relative and absolute paths</Run></Bold><Run Foreground="White"> - accepts both path types in the configuration.</Run><LineBreak/>
<Run Foreground="White">✅ </Run><Bold><Run Foreground="LimeGreen">Failure isolation</Run></Bold><Run Foreground="White"> - continues the loop when individual files are missing or return a handled failure.</Run><LineBreak/>
<Run Foreground="White">✅ </Run><Bold><Run Foreground="LimeGreen">Command line logging</Run></Bold><Run Foreground="White"> - reports loading progress inside AutoCAD.</Run><LineBreak/>
<Run Foreground="White">✅ </Run><Bold><Run Foreground="LimeGreen">Rolling disk log</Run></Bold><Run Foreground="White"> - writes LispLoader.log and rotates it at 5 MB.</Run><LineBreak/>
<Run Foreground="White">✅ </Run><Bold><Run Foreground="LimeGreen">Version banner</Run></Bold><Run Foreground="White"> - prints version and build timestamp when the plugin initializes.</Run><LineBreak/>
<LineBreak/>
<Bold><Run Foreground="DarkRed">Important Notes</Run></Bold><LineBreak/>
<Run Foreground="White">⚠️ </Run><Bold><Run Foreground="DarkRed">Project version is 1.0.000.</Run></Bold><LineBreak/>
<Run Foreground="White">⚠️ </Run><Bold><Run Foreground="DarkRed">The provided LoaderConfig contains example entries for DLL LSP FAS and VLX files.</Run></Bold><LineBreak/>
<Run Foreground="White">⚠️ </Run><Bold><Run Foreground="DarkRed">The README recommends placing DLL entries before dependent LISP files.</Run></Bold><LineBreak/>
<Run Foreground="White">⚠️ </Run><Bold><Run Foreground="DarkRed">The LSP load path is sent asynchronously with SendStringToExecute so the immediate OK log represents successful dispatch rather than a full parser level verification of the target LISP result.</Run></Bold><LineBreak/>
<Run Foreground="White">⚠️ </Run><Bold><Run Foreground="DarkRed">An active AutoCAD document is required for LSP VLX and FAS dispatch.</Run></Bold><LineBreak/>
<LineBreak/>
<Bold><Run Foreground="Yellow">SEO Keywords</Run></Bold><LineBreak/>
<Run Foreground="Yellow">🏷️ AutoCAD 🏷️ Civil 3D 🏷️ LispLoader 🏷️ AutoLISP loader 🏷️ VLX loader 🏷️ FAS loader 🏷️ DLL loader 🏷️ LoaderConfig 🏷️ ExtensionLoader 🏷️ AutoCAD startup 🏷️ Rolling log 🏷️ CAD automation</Run><LineBreak/>
<LineBreak/>
</TextBlock>
</StackPanel>
</src:RibbonToolTip.ExpandedContent>
</src:RibbonToolTip>
</ResourceDictionary>
C# code:
// ===== FILE: ConfigReader.cs =====
using System;
using System.Collections.Generic;
using System.IO;
namespace LispLoader
{
/// <summary>
/// Reads LoaderConfig.txt from the fixed base folder.
///
/// File format (one entry per line):
/// # This is a comment — ignored
/// ; This is also a comment — ignored
/// ← blank lines ignored
/// C:\full\path\to\file.lsp ← absolute path
/// Polyline_menu\QuickMirror\QuickMirror.lsp ← relative to base folder
///
/// Relative paths are resolved against the base folder:
/// C:\Users\mateid\...\Help_File\
/// </summary>
internal static class ConfigReader
{
private const string Source = "ConfigReader";
private static readonly string BaseFolder =
@"C:\Users\mateid\OneDrive - DB E.C.O. Group\@C3D\@Dan_Templates\Acad\Support_files\Lisps\Help_File";
private static readonly string ConfigFile =
Path.Combine(BaseFolder, "LoaderConfig.txt");
/// <summary>
/// Returns the list of resolved absolute paths to load.
/// Missing or unreadable config returns an empty list (logged as error).
/// </summary>
internal static IReadOnlyList<string> ReadPaths()
{
if (!File.Exists(ConfigFile))
{
LogManager.Error(Source, $"Config file not found: {ConfigFile}");
LogManager.Warn (Source, "Create LoaderConfig.txt in the base folder.");
return Array.Empty<string>();
}
var paths = new List<string>();
try
{
string[] lines = File.ReadAllLines(ConfigFile);
int lineNo = 0;
foreach (string raw in lines)
{
lineNo++;
string line = raw.Trim();
// Skip blanks and comments
if (string.IsNullOrEmpty(line)) continue;
if (line.StartsWith("#")) continue;
if (line.StartsWith(";")) continue;
// Resolve relative paths
string resolved = Path.IsPathRooted(line)
? line
: Path.Combine(BaseFolder, line);
paths.Add(resolved);
}
LogManager.Info(Source, $"Config loaded: {paths.Count} entries from {ConfigFile}");
}
catch (Exception ex)
{
LogManager.Error(Source, $"Failed to read config: {ex.Message}");
}
return paths;
}
}
}
// ===== FILE: FileLoader.cs =====
using System;
using System.IO;
using System.Reflection;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
namespace LispLoader
{
/// <summary>
/// Loads individual files safely — one failure never stops the next file.
///
/// Supported types:
/// .lsp .vlx .fas → Editor.RunLisp( (load "path") )
/// .dll → Assembly.LoadFrom + ExtensionLoader
/// </summary>
internal static class FileLoader
{
private const string Source = "FileLoader";
// ── Public entry point ────────────────────────────────────────────────
/// <summary>
/// Load a single file. Swallows all exceptions and logs the result.
/// Returns true on success.
/// </summary>
internal static bool Load(string path)
{
if (string.IsNullOrWhiteSpace(path))
return false;
path = path.Trim();
if (!File.Exists(path))
{
LogManager.Warn(Source, $"[NOT FOUND] {path}");
return false;
}
string ext = Path.GetExtension(path).ToLowerInvariant();
return ext switch
{
".lsp" or ".vlx" or ".fas" => LoadLisp(path),
".dll" => LoadDll(path),
_ => UnsupportedType(path, ext),
};
}
// ── LSP / VLX / FAS ──────────────────────────────────────────────────
private static bool LoadLisp(string path)
{
try
{
// Escape backslashes for the LISP string
string escaped = path.Replace("\\", "\\\\");
string expr = $"(load \"{escaped}\")";
Document? doc = Application.DocumentManager?.MdiActiveDocument;
if (doc == null)
throw new InvalidOperationException("No active document.");
// RunLisp evaluates silently — no command echo on the prompt
doc.SendStringToExecute(expr + "\n", false, false, false);
// RunLisp does not return a catchable error for LOAD failures;
// we use a second expression to check if the load produced an error atom.
// The reliable signal is the absence of an exception here —
// any reader-level crash in the target file surfaces as an Exception.
LogManager.Info(Source, $"[OK] {path}");
return true;
}
catch (System.Exception ex)
{
LogManager.Error(Source, $"[FAIL-LISP] {path}");
LogManager.Error(Source, $" {ex.Message}");
return false;
}
}
// ── DLL ──────────────────────────────────────────────────────────────
private static bool LoadDll(string path)
{
try
{
// Step 1 — load the assembly into the AppDomain
Assembly asm = Assembly.LoadFrom(path);
// Step 2 — register it with AutoCAD's ExtensionLoader
// so IExtensionApplication.Initialize() is called
ExtensionLoader.Load(path);
string name = asm.GetName().Name ?? Path.GetFileName(path);
string version = asm.GetName().Version?.ToString() ?? "?";
LogManager.Info(Source, $"[OK-DLL] {name} v{version}");
LogManager.Info(Source, $" {path}");
return true;
}
catch (System.Exception ex)
{
LogManager.Error(Source, $"[FAIL-DLL] {path}");
LogManager.Error(Source, $" {ex.Message}");
return false;
}
}
// ── Helpers ───────────────────────────────────────────────────────────
private static bool UnsupportedType(string path, string ext)
{
LogManager.Warn(Source, $"[SKIP] Unsupported extension '{ext}': {path}");
return false;
}
}
}
// ===== FILE: VersionStamp.cs =====
using System;
using System.Linq;
using System.Reflection;
namespace LispLoader
{
/// <summary>
/// Prints the version banner whenever the plugin loads.
///
/// Format: v1.0.000 | built 12.06.2026 10:30:00
///
/// Version → AssemblyVersion set in <Version> in the .csproj
/// Timestamp → AssemblyMetadata("BuildTimestamp", "dd.MM.yyyy_HH.mm.ss")
/// injected at compile time by the MSBuild SetBuildTimestamp target.
/// No generated .cs file required.
/// </summary>
internal static class VersionStamp
{
private const string Source = "LispLoader";
internal static void Print()
{
Assembly asm = Assembly.GetExecutingAssembly();
// ── Version ───────────────────────────────────────────────────────
string version = asm.GetName().Version?.ToString(3) ?? "?.?.???";
// ── Timestamp from AssemblyMetadata ───────────────────────────────
// The .csproj target adds:
// [assembly: AssemblyMetadata("BuildTimestamp", "12.06.2026_10.30.00")]
string raw = asm
.GetCustomAttributes<AssemblyMetadataAttribute>()
.FirstOrDefault(a => a.Key == "BuildTimestamp")
?.Value
?? "??.??.????_??.??.??";
// raw = "12.06.2026_10.30.00"
string[] halves = raw.Split('_');
string date = halves.Length > 0 ? halves[0] : "??"; // 12.06.2026
string time = halves.Length > 1 ? halves[1].Replace('.', ':') : "??"; // 10:30:00
string banner = $"v{version} | built {date} {time}";
LogManager.Separator();
LogManager.Info(Source, banner);
LogManager.Separator();
}
}
}
// ===== FILE: LogManager.cs =====
using System;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
namespace LispLoader
{
/// <summary>
/// Log levels for filtering output.
/// </summary>
internal enum LogLevel { INFO, WARN, ERROR }
/// <summary>
/// Writes timestamped log lines to both the AutoCAD command line
/// and a persistent .log file on disk.
///
/// Format: HH:mm:ss [LEVEL] [Source] message
/// Example: 05:29:43 [INFO] [LispLoader] Loaded ObjectPropExtra.dll
/// </summary>
internal static class LogManager
{
// ── Config ────────────────────────────────────────────────────────────
private static readonly string LogFolder =
@"C:\Users\mateid\OneDrive - DB E.C.O. Group\@C3D\@Dan_Templates\Acad\Support_files\Lisps\Help_File";
private static readonly string LogFile =
Path.Combine(LogFolder, "LispLoader.log");
// Maximum log file size before it is rotated (5 MB)
private const long MaxLogBytes = 5 * 1024 * 1024;
// ── Public API ────────────────────────────────────────────────────────
internal static void Info(string source, string message)
=> Write(LogLevel.INFO, source, message);
internal static void Warn(string source, string message)
=> Write(LogLevel.WARN, source, message);
internal static void Error(string source, string message)
=> Write(LogLevel.ERROR, source, message);
internal static void Separator()
=> Write(null, null, new string('─', 72));
// ── Core ──────────────────────────────────────────────────────────────
private static void Write(LogLevel? level, string? source, string message)
{
string line = Format(level, source, message);
// 1. AutoCAD command line
try
{
Document? doc = Application.DocumentManager?.MdiActiveDocument;
Editor? ed = doc?.Editor;
ed?.WriteMessage("\n" + line);
}
catch { /* editor unavailable during early init — swallow */ }
// 2. Disk log
try
{
RotateIfNeeded();
File.AppendAllText(LogFile, line + Environment.NewLine);
}
catch { /* disk unavailable — swallow */ }
}
private static string Format(LogLevel? level, string? source, string message)
{
string ts = DateTime.Now.ToString("HH:mm:ss");
string lvl = level.HasValue ? $"[{level.Value,-5}]" : " ";
string src = source != null ? $"[{source}]" : string.Empty;
return $"{ts} {lvl} {src,-20} {message}";
}
private static void RotateIfNeeded()
{
if (!File.Exists(LogFile)) return;
var info = new FileInfo(LogFile);
if (info.Length < MaxLogBytes) return;
// Rename current log to .bak (overwrite previous backup)
string bak = Path.ChangeExtension(LogFile, ".bak.log");
if (File.Exists(bak)) File.Delete(bak);
File.Move(LogFile, bak);
}
}
}
// ===== FILE: LispLoader.cs =====
using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
// Register this assembly as an AutoCAD extension
[assembly: ExtensionApplication(typeof(LispLoader.LispLoaderApp))]
namespace LispLoader
{
/// <summary>
/// Entry point for the LispLoader AutoCAD plugin.
///
/// AutoCAD calls Initialize() immediately after _.netload completes.
/// Terminate() is called when AutoCAD shuts down.
///
/// Usage — paste once into the AutoCAD command prompt:
/// (command "_.netload" "C:\\...\\LispLoader.dll")
/// </summary>
public class LispLoaderApp : IExtensionApplication
{
private const string Source = "LispLoader";
// ── IExtensionApplication ─────────────────────────────────────────────
public void Initialize()
{
// 1. Banner with version + build timestamp
VersionStamp.Print();
// 2. Read the config file
IReadOnlyList<string> paths = ConfigReader.ReadPaths();
if (paths.Count == 0)
{
LogManager.Warn(Source, "Nothing to load — check LoaderConfig.txt.");
LogManager.Separator();
return;
}
// 3. Load each file — failures are isolated, loading always continues
int ok = 0;
int fail = 0;
int skip = 0;
LogManager.Info(Source, $"Starting load sequence: {paths.Count} file(s)");
LogManager.Separator();
foreach (string path in paths)
{
bool result = FileLoader.Load(path);
if (result) ok++;
else if (System.IO.File.Exists(path)) fail++;
else skip++;
}
// 4. Summary
LogManager.Separator();
LogManager.Info(Source, $"Load complete — OK: {ok} FAILED: {fail} SKIPPED (not found): {skip}");
LogManager.Separator();
}
public void Terminate()
{
LogManager.Info(Source, "LispLoader unloaded.");
}
}
}
