Version: 24.1.0 "Altair-R" Last Updated: March 28, 2026 Target Audience: Contributors, Plugin Developers, Maintainers Build Status: 0 errors, 0 warnings (Release x64)
- Architecture Overview
- Development Setup
- Building from Source
- Code Structure
- Contributing Guidelines
- Testing
- Debugging
┌─────────────────────────────────────────────────────┐
│ Windows Explorer (Shell) │
└─────────────────┬───────────────────────────────────┘
│ IThumbnailProvider Interface
▼
┌─────────────────────────────────────────────────────┐
│ LENSShell.dll (Shell Extension) │
│ ┌────────────────────────────────────────────────┐ │
│ │ LENSShellClass (IThumbnailProvider impl) │ │
│ │ - COM Registration │ │
│ │ - IThumbnailProvider::GetThumbnail() │ │
│ │ - SEH Exception Handling │ │
│ └─────────────────┬──────────────────────────────┘ │
└────────────────────┼────────────────────────────────┘
│ Engine API
▼
┌─────────────────────────────────────────────────────┐
│ ExplorerLensEngine.lib (Core Engine) │
│ ┌────────────────────────────────────────────────┐ │
│ │ ImageEngine (Main API) │ │
│ │ - InitializeForThumbnails() │ │
│ │ - CreateThumbnailFromFile() │ │
│ └─────────────────┬──────────────────────────────┘ │
│ │ │
│ ┌────────────────┼──────────────────────────────┐ │
│ │ Decoder Pipeline │ │
│ │ ├─ Archive Decoders (ZIP, RAR, 7Z, CBZ/CBR) │ │
│ │ ├─ Image Decoders (JPEG, PNG, WebP, JXL │ │
│ │ ├─ RAW Decoders (CR2, NEF, ARW via LibRaw) │ │
│ │ ├─ Video Decoders (MP4, MKV via DirectShow) │ │
│ │ └─ Audio Decoders (MP3, FLAC album art) │ │
│ └─────────────────┬──────────────────────────────┘ │
│ │ │
│ ┌────────────────┼──────────────────────────────┐ │
│ │ GPU Acceleration (D3D11) │ │
│ │ - SIMDScaler (AVX2 optimized resizing) │ │
│ │ - D3D11TextureRenderer (GPU compositing) │ │
│ │ - Shader compilation & caching │ │
│ └───────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ External Libraries (Static linking) │
│ - zlib 1.3.1, zstd 1.5.7, LZ4 1.10.0, LZMA 26.00 │
│ - minizip-ng 4.0.10, UnRAR 7.2.2 │
│ - libwebp 1.5.0, libjxl 0.11.1 │
│ - LibRaw 0.21.3 (RAW photos) │
│ - DirectX 11, Windows WIC │
└─────────────────────────────────────────────────────┘
- LENSShell.dll - Windows Shell Extension (COM DLL)
- Implements
IThumbnailProviderCOM interface - Handles Explorer integration
- SEH exception protection wrapper
- Delegates to
ExplorerLensEngine.lib
- ExplorerLensEngine.lib - Core thumbnail engine (static library)
- Format detection and dispatching
- Decoder implementations
- GPU acceleration via DirectX 11
- SIMD-optimized image processing
- Circuit breaker pattern for failing decoders
- LENSManager.exe - Configuration utility (WinUI 3 / Win32)
- Handler registration/unregistration
- Cache management
- GPU selection
- Statistics and diagnostics
Install using the provided script:
.\scripts\Setup-DevEnvironment.ps1Or manually install:
-
Visual Studio 2026 (18.x+) with:
-
C++ desktop development workload
-
Windows 11 SDK (10.0.22621.0+)
-
CMake tools
-
Build Tools:
-
CMake 3.28+
-
Ninja 1.11+
-
PowerShell 7+
-
Compilers:
-
MSVC v145+ (Visual Studio 2026)
-
Clang 17+ (optional, for LLVM builds)
-
Verification:
.\scripts\verify-tools.ps1ExplorerLens/
├── Engine/ # Core thumbnail engine (C++20)
│ ├── Core/ # API surface, initialization
│ ├── Decoders/ # Format-specific decoders
│ ├── GPU/ # DirectX 11 acceleration
│ ├── Utils/ # Utilities, SIMD, profiling
│ └── CMakeLists.txt
│
├── LENSShell/ # Shell extension (COM DLL)
│ ├── LENSShellClass.cpp/.h # IThumbnailProvider impl
│ ├── LENSShell.idl # COM interface definition
│ └── LENSShell.vcxproj # MSBuild project
│
├── LENSManager/ # Configuration utility
│ ├── MainDlg.cpp/.h # Main dialog
│ ├── DarkModeHelper.h # Dark mode support
│ └── LENSManager.vcxproj
│
├── external/ # Third-party libraries
│ ├── compression-libs/ # zlib, zstd, lz4, lzma, minizip-ng
│ ├── archive-libs/ # unrar
│ ├── image-libs/ # libwebp, libjxl
│ └── camera-libs/ # LibRaw
│
├── build-scripts/ # Build automation
│ ├── external-libs/ # Library build scripts
│ ├── production/ # Production build pipelines
│ └── Build-With-Monitoring.ps1
│
├── tests/ # Unit tests (Google Test)
├── docs/ # Documentation
├── packaging/ # WiX installer
└── CMakeLists.txt # CMake entry point
# Complete build: dependencies, engine, solution, and MSI installer
.\build-scripts\Build-All-And-Package.ps1 -Configuration Release -Version 7.0.0
# Skip dependencies if already built (faster)
.\build-scripts\Build-All-And-Package.ps1 -SkipDependencies
# Clean build (rebuild from scratch)
.\build-scripts\Build-All-And-Package.ps1 -Clean
# Or use Visual Studio task
# Ctrl+Shift+B → "Build Release (Standard)"# Full build with dependencies (uses old build system)
.\scripts\build.ps1 -Configuration Release
# Or use Visual Studio task
# Ctrl+Shift+B → "Build Release (Standard)"# vcpkg can be used for future dependency management
.\build-scripts\Setup-Vcpkg.ps1
# With package installation
.\build-scripts\Setup-Vcpkg.ps1 -InstallPackages
# Note: ExplorerLens currently builds most libraries from sourceNEW v7.0 Refactored Scripts (Recommended):
# Using new unified build modules (50% less code)
.\build-scripts\external-libs\Build-LibWebP-NMake.ps1 -Configuration Release -Clean
.\build-scripts\external-libs\Build-MinizipNG.ps1 -Configuration Release -Clean
.\build-scripts\external-libs\build-libjxl.ps1 -Configuration Release -Clean
.\build-scripts\external-libs\build-libavif.ps1 -Configuration Release -Clean
# Remaining libraries (legacy scripts - being refactored)
.\build-scripts\external-libs\build-lzma-sdk-26.00.ps1
.\build-scripts\external-libs\Build-Zlib.ps1
.\build-scripts\external-libs\Build-Zstd.ps1Legacy Method:
# Build all external libraries with /MD runtime (4-6 hours)
.\build-scripts\Rebuild-All-With-MD.ps1 -Clean
# Or build individually (old scripts)
.\build-scripts\external-libs\build-lzma-sdk-26.00.ps1
.\build-scripts\external-libs\Build-LibWebP-NMake.ps1
.\build-scripts\external-libs\Build-MinizipNG.ps1💡 TIP: Use the new
Build-All-And-Package.ps1script to build everything automatically.
# Configure
cmake -S . -B build -G Ninja `
-DCMAKE_BUILD_TYPE=Release `
-DCMAKE_CXX_COMPILER=clang++ `
-DCMAKE_C_COMPILER=clang
# Build
cmake --build build --config Release --target ExplorerLensEngine -j 8
# Output: build/lib/Release/ExplorerLensEngine.libmsbuild LENSShell.sln /p:Configuration=Release /p:Platform=x64 /t:LENSShell /m
# Output: x64/Release/LENSShell.dllmsbuild LENSShell.sln /p:Configuration=Release /p:Platform=x64 /t:LENSManager /m
# Output: x64/Release/LENSManager.exe| Configuration | Compiler | Optimization | Debug Info | Runtime |
|---|---|---|---|---|
| Debug | MSVC | O0 | Full | /MDd |
| Release | MSVC/Clang | O2/O3 | None | /MD |
| RelWithDebInfo | MSVC | O2 | Full | /MD |
Header: Engine/Core/EngineAPI.h
class ExplorerLensEngine {
public:
static bool InitializeForThumbnails(HWND hwnd = nullptr);
static bool CreateThumbnailFromFile(
LPCWSTR pszPath,
UINT cx, // Requested width
HBITMAP* phBitmap,
WTS_ALPHATYPE* pdwAlpha
);
static void Shutdown();
};All decoders implement:
class IDecoder {
public:
virtual ~IDecoder() = default;
virtual bool CanDecode(const std::wstring& extension) = 0;
virtual DecoderResult Decode(
const std::wstring& filePath,
uint32_t maxWidth,
uint32_t maxHeight
) = 0;
};- Create decoder class in
Engine/Decoders/:
// Engine/Decoders/PNGDecoder.h
class PNGDecoder : public IDecoder {
public:
bool CanDecode(const std::wstring& extension) override;
DecoderResult Decode(...) override;
private:
// Implementation
};- Register in
Engine/Core/DecoderRegistry.cpp:
void DecoderRegistry::Initialize() {
RegisterDecoder(std::make_unique<PNGDecoder>());
// ... other decoders
}- Add tests in
tests/DecoderTests/:
TEST(PNGDecoderTest, DecodeValidPNG) {
PNGDecoder decoder;
auto result = decoder.Decode(L"test.png", 256, 256);
ASSERT_TRUE(result.success);
ASSERT_NE(result.bitmap, nullptr);
}- C++ Standard: C++20
- Formatting: clang-format (Google style)
- Naming:
- Classes:
PascalCase - Functions:
PascalCase - Variables:
camelCase - Constants:
UPPER_SNAKE_CASE
- Fork the repository
- Create branch from
main:
git checkout -b feature/amazing-decoder- Implement your changes
- Add tests (required for new features)
- Run test suite:
ctest --test-dir build --output-on-failure- Build with zero warnings:
msbuild /p:TreatWarningsAsErrors=true- Submit PR with:
- Clear description
- Test coverage report
- Before/after performance metrics (if applicable)
Follow conventional commits:
feat: Add TIFF decoder with BigTIFF support
fix: Resolve memory leak in WebP decoder
docs: Update build instructions for Clang 17
perf: Optimize SIMD scaler with AVX-512
test: Add fuzzing tests for RAR archives
# Build tests
cmake --build build --target ExplorerLensTests
# Run all tests
ctest --test-dir build --output-on-failure
# Run specific test
.\build\tests\ExplorerLensTests.exe --gtest_filter=*PNGDecoder*# Test with real file corpus
.\tests\Integration-Tests.ps1
# Performance benchmarks
.\tests\Performance-Tests.ps1# Enable CRT debug heap
$env:_NO_DEBUG_HEAP = 0
.\build\tests\ExplorerLensTests.exe
# Or use Application Verifier
appverif /verify handles locks heaps memory /for LENSShell.dllShell extensions run in Explorer process. Use:
# Method 1: Attach to Explorer
# 1. Build Debug configuration
# 2. Open Visual Studio → Debug → Attach to Process → explorer.exe
# 3. Set breakpoint in LENSShellClass::GetThumbnail
# 4. Navigate to folder with target file in Explorer
# Method 2: Standalone test harness
.\tests\ShellExtensionTestHarness.exe "path\to\file.cbz"Enable debug output:
// Engine/Utils/DebugLog.h
#define ExplorerLens_DEBUG_LOG 1
// Logs to OutputDebugString, viewable in DebugView
LOG_DEBUG(L"Decoding file: %s", filePath.c_str());
LOG_ERROR(L"Failed to decode: %s (HRESULT: 0x%08X)", filePath.c_str(), hr);View logs with DebugView (Sysinternals):
# Download and run
.\DebugView.exe
# Filter: ExplorerLens*# Visual Studio Profiler
# 1. Build RelWithDebInfo
# 2. Alt+F2 → Performance Profiler → CPU Usage
# 3. Attach to explorer.exe
# 4. Navigate to test folder
# Or use Tracy Profiler (integrated)
# Macro: PROFILE_FUNCTION() at function entry- Build Instructions: build-method.md
- Library Inventory: external/LIBRARY_INVENTORY.md
- User Guide: USER_GUIDE.md
- Plugin SDK: SDK/docs/PLUGIN_SDK.md
Questions? Open an issue on GitHub or contact maintainers.
Happy coding! 🚀