Skip to content

Helper Classes

Calvindd2f edited this page Jan 14, 2026 · 1 revision

Helper Classes

Relevant source files

The following files were used as context for generating this wiki page:

Purpose and Scope

This document provides an overview of the nine specialized helper classes in the OfficeScrubNative namespace that implement high-performance system operations for Office removal. These classes form the core of the native performance layer, providing 10-50x speedup over PowerShell-only implementations.

For the complete native library architecture, see Native Library Overview. For detailed documentation of individual helper classes, see RegistryHelper, FileHelper, ProcessHelper, WindowsInstallerHelper, and Additional Helpers. For the underlying Win32 API usage, see P/Invoke and Win32 APIs.


Helper Class Architecture

The native library implements a modular helper class architecture where each class encapsulates operations for a specific Windows subsystem. All helpers are instantiated and coordinated by the OfficeScrubOrchestrator class.

graph TB
    subgraph "OfficeScrubNative.dll"
        Orchestrator["OfficeScrubOrchestrator<br/>Facade & Coordinator"]
        
        subgraph "Core System Helpers"
            RegHelper["RegistryHelper<br/>30x faster registry ops"]
            FileHelper["FileHelper<br/>15x faster file ops"]
            ProcHelper["ProcessHelper<br/>Parallel termination"]
        end
        
        subgraph "Windows Installer Helpers"
            WIHelper["WindowsInstallerHelper<br/>MSI metadata cleanup"]
            TypeLibHelper["TypeLibHelper<br/>COM TypeLib cleanup"]
        end
        
        subgraph "Office-Specific Helpers"
            LicenseHelper["LicenseHelper<br/>SPP/OSPP operations"]
            ServiceHelper["ServiceHelper<br/>Service management"]
        end
        
        subgraph "Utility Helpers"
            GuidHelper["GuidHelper<br/>Static GUID utils"]
            ShellHelper["ShellHelper<br/>Shell integration"]
        end
    end
    
    subgraph "Win32 APIs"
        AdvApi["advapi32.dll<br/>RegOpenKeyEx<br/>RegDeleteKeyEx"]
        Kernel["kernel32.dll<br/>MoveFileEx<br/>RemoveDirectory"]
        Shell32["shell32.dll<br/>ILCreateFromPath<br/>SHCreateShellItem"]
        WMI["WMI<br/>Win32_Service<br/>SoftwareLicensingProduct"]
    end
    
    Orchestrator --> RegHelper
    Orchestrator --> FileHelper
    Orchestrator --> ProcHelper
    Orchestrator --> WIHelper
    Orchestrator --> TypeLibHelper
    Orchestrator --> LicenseHelper
    Orchestrator --> ServiceHelper
    Orchestrator --> GuidHelper
    Orchestrator --> ShellHelper
    
    WIHelper --> RegHelper
    TypeLibHelper --> RegHelper
    
    RegHelper --> AdvApi
    FileHelper --> Kernel
    ShellHelper --> Shell32
    LicenseHelper --> WMI
    ServiceHelper --> WMI
Loading

Sources: OfficeScrubC2R-Native.cs:17-1408


Helper Class Responsibilities

The following table categorizes each helper class by its primary responsibility and key operations:

Helper Class Primary Responsibility Key Operations Win32 APIs Used Lines
GuidHelper GUID format conversion GetExpandedGuid, GetCompressedGuid, GetDecodedGuid None (pure C#) 171-328
RegistryHelper Registry operations with WOW64 support KeyExists, DeleteKey, EnumerateKeys, GetValue, SetValue RegOpenKeyEx, RegDeleteKeyEx, RegEnumKeyEx 334-616
FileHelper File/directory operations with reboot scheduling DeleteFile, DeleteDirectory, ScheduleDeleteOnReboot MoveFileEx, RemoveDirectory, SetFileAttributes 622-767
ProcessHelper Parallel process termination TerminateProcesses, GetProcessesUsingPath, IsProcessRunning Process API (managed) 773-858
ShellHelper Shell integration cleanup UnpinFromTaskbar, UnpinFromStartMenu, RestartExplorer Shell COM automation 864-974
WindowsInstallerHelper MSI metadata cleanup CleanupUpgradeCodes, CleanupProducts, CleanupComponents Registry via RegistryHelper 980-1128
TypeLibHelper COM TypeLib cleanup CleanupKnownTypeLibs Registry via RegistryHelper 1134-1209
LicenseHelper License operations CleanOSPP, ClearVNextLicenseCache WMI (SoftwareLicensingProduct) 1215-1273
ServiceHelper Windows service management DeleteService WMI (Win32_Service), sc.exe 1279-1343
OfficeScrubOrchestrator Facade & coordination Instantiates all helpers, provides IsC2RPath, IsInScope All helpers 1349-1407

Sources: OfficeScrubC2R-Native.cs:17-1408


Helper Class Categories

The nine helper classes can be logically grouped into four categories based on their operational domain:

Core System Operations

These helpers provide fundamental system-level operations that form the foundation for all cleanup activities.

graph LR
    subgraph "Core System Helpers"
        RegHelper["RegistryHelper"]
        FileHelper["FileHelper"]
        ProcHelper["ProcessHelper"]
    end
    
    RegHelper --> WOW64["WOW64 Support<br/>32/64-bit views"]
    RegHelper --> RecursiveDel["Recursive Deletion<br/>DeleteSubKeyTree"]
    RegHelper --> PendingReg["PendingFileRename<br/>Registry operations"]
    
    FileHelper --> CmdRd["cmd.exe rd /s /q<br/>Fast deletion"]
    FileHelper --> RebootSched["MoveFileEx<br/>Reboot scheduling"]
    FileHelper --> AttrClear["SetFileAttributes<br/>ReadOnly removal"]
    
    ProcHelper --> ParallelTerm["Task.Run<br/>Parallel termination"]
    ProcHelper --> TimeoutMgmt["Timeout Management<br/>WaitForExit"]
    ProcHelper --> SafeDispose["Safe Disposal<br/>finally blocks"]
Loading

Sources: OfficeScrubC2R-Native.cs:334-858

Windows Installer Operations

These helpers manage Windows Installer metadata and COM registrations.

graph TB
    subgraph "Windows Installer Helpers"
        WIHelper["WindowsInstallerHelper"]
        TypeLibHelper["TypeLibHelper"]
    end
    
    WIHelper --> UpgradeCodes["CleanupUpgradeCodes<br/>HKLM\\...\\UpgradeCodes"]
    WIHelper --> Products["CleanupProducts<br/>HKLM\\...\\Products<br/>HKCR\\Installer\\Products"]
    WIHelper --> Components["CleanupComponents<br/>HKLM\\...\\Components"]
    WIHelper --> PubComponents["CleanupPublishedComponents<br/>HKCR\\Installer\\Components"]
    
    TypeLibHelper --> KnownTL["CleanupKnownTypeLibs<br/>14 known Office TypeLibs"]
    TypeLibHelper --> VerCheck["Version Checking<br/>Win32/Win64 paths"]
    TypeLibHelper --> FileVerify["File Existence Verification<br/>Before deletion"]
    
    WIHelper --> GuidDecode["Uses GuidHelper<br/>Compressed GUID conversion"]
    WIHelper --> RegOps["Uses RegistryHelper<br/>All registry operations"]
    TypeLibHelper --> RegOps2["Uses RegistryHelper<br/>All registry operations"]
Loading

Sources: OfficeScrubC2R-Native.cs:980-1209

Office-Specific Operations

These helpers implement operations unique to Office products.

graph TB
    subgraph "Office-Specific Helpers"
        LicenseHelper["LicenseHelper"]
        ServiceHelper["ServiceHelper"]
    end
    
    LicenseHelper --> OSPP["CleanOSPP<br/>SoftwareLicensingProduct WMI"]
    LicenseHelper --> VNext["ClearVNextLicenseCache<br/>LocalAppData\\Office\\Licenses"]
    LicenseHelper --> SPP["SPP/OSPP Detection<br/>Version-dependent class names"]
    
    ServiceHelper --> WMIStop["WMI Service Operations<br/>StopService + Delete"]
    ServiceHelper --> ScFallback["sc.exe Fallback<br/>When WMI fails"]
    ServiceHelper --> StateCheck["Service State Checking<br/>Running/Started detection"]
    
    LicenseHelper --> VersionNT["Version Detection<br/>Windows 7 vs 8+ logic"]
Loading

Sources: OfficeScrubC2R-Native.cs:1215-1343, docs/memory-bank/product.md:1-62

Utility Operations

These helpers provide supporting functionality used across multiple operations.

graph LR
    subgraph "Utility Helpers"
        GuidHelper["GuidHelper<br/>Static utility class"]
        ShellHelper["ShellHelper<br/>Shell COM automation"]
    end
    
    GuidHelper --> Expand["GetExpandedGuid<br/>32-char → 38-char GUID"]
    GuidHelper --> Compress["GetCompressedGuid<br/>38-char → 32-char GUID"]
    GuidHelper --> Decode["GetDecodedGuid<br/>Base85 → GUID"]
    GuidHelper --> ReverseOps["Reverse<br/>Internal helper"]
    
    ShellHelper --> UnpinTask["UnpinFromTaskbar<br/>Shell verb automation"]
    ShellHelper --> UnpinStart["UnpinFromStartMenu<br/>Shell verb automation"]
    ShellHelper --> ExplorerRestart["RestartExplorer<br/>Process management"]
    ShellHelper --> I18N["Localized Verb Support<br/>10 languages"]
Loading

Sources: OfficeScrubC2R-Native.cs:171-328, OfficeScrubC2R-Native.cs:864-974


Orchestrator Coordination Pattern

The OfficeScrubOrchestrator class implements the Facade pattern, providing a unified interface to all helper classes and managing their instantiation and dependencies.

graph TB
    PowerShell["PowerShell Layer<br/>OfficeScrubC2R.psm1<br/>OfficeScrubC2R-Utilities.psm1"]
    
    subgraph "OfficeScrubOrchestrator"
        direction TB
        Constructor["Constructor<br/>bool is64Bit parameter"]
        Props["Public Properties<br/>Registry, Files, Processes<br/>Shell, WindowsInstaller<br/>TypeLib, License, Services"]
        Utils["Utility Methods<br/>IsC2RPath<br/>IsInScope"]
    end
    
    subgraph "Helper Instantiation"
        direction LR
        Reg["Registry = new RegistryHelper is64Bit"]
        File["Files = new FileHelper"]
        Proc["Processes = new ProcessHelper"]
        Shell["Shell = new ShellHelper"]
        WI["WindowsInstaller = new WindowsInstallerHelper Registry"]
        TL["TypeLib = new TypeLibHelper Registry"]
        Lic["License = new LicenseHelper"]
        Svc["Services = new ServiceHelper"]
    end
    
    PowerShell --> Constructor
    Constructor --> Props
    Props --> Reg
    Props --> File
    Props --> Proc
    Props --> Shell
    Props --> WI
    Props --> TL
    Props --> Lic
    Props --> Svc
    
    WI -.depends on.-> Reg
    TL -.depends on.-> Reg
Loading

Orchestrator Implementation

The orchestrator maintains public property references to all helpers, allowing PowerShell code to access them through dot notation:

// Instantiation pattern
public OfficeScrubOrchestrator(bool is64Bit)
{
    Registry = new RegistryHelper(is64Bit);
    Files = new FileHelper();
    Processes = new ProcessHelper();
    Shell = new ShellHelper();
    WindowsInstaller = new WindowsInstallerHelper(Registry);  // Dependency injection
    TypeLib = new TypeLibHelper(Registry);                    // Dependency injection
    License = new LicenseHelper();
    Services = new ServiceHelper();
}

Key Design Decisions:

  1. Property-based access: Each helper is exposed as a public property rather than through methods, simplifying PowerShell interop
  2. Constructor injection: WindowsInstallerHelper and TypeLibHelper receive RegistryHelper dependency in constructor
  3. 64-bit awareness: Only RegistryHelper needs is64Bit parameter; file system automatically handles architecture
  4. Single instantiation: Each helper is instantiated once per orchestrator lifetime

Sources: OfficeScrubC2R-Native.cs:1349-1407


Common Implementation Patterns

All helper classes follow consistent design patterns to ensure reliability and performance:

Pattern 1: Silent Failure with Boolean Returns

All destructive operations return bool indicating success/failure, never throwing exceptions:

// RegistryHelper example
public bool DeleteKey(RegistryHiveType hive, string subKey, bool recursive = true)
{
    try
    {
        if (recursive)
            hive.DeleteSubKeyTree(subKey, false);
        else
            hive.DeleteSubKey(subKey, false);
        return true;
    }
    catch
    {
        return false;
    }
}

Rationale: Office cleanup must be resilient to errors. Individual operation failures should not halt the entire cleanup process.

Sources: OfficeScrubC2R-Native.cs:538-551, docs/memory-bank/guidelines.md:24-38

Pattern 2: WOW64 Dual-View Operations

RegistryHelper automatically checks both 32-bit and 64-bit registry views on 64-bit systems:

public bool DeleteKey(RegistryHiveType hive, string subKey, bool recursive = true)
{
    bool result = false;
    
    if (KeyExists(hive, subKey))
    {
        result = DeleteKeyInternal(GetHiveKey(hive), subKey, recursive);
    }
    
    if (_is64Bit && KeyExists(hive, GetWow64Key(subKey)))  // Check 32-bit view
    {
        result = DeleteKeyInternal(GetHiveKey(hive), GetWow64Key(subKey), recursive) || result;
    }
    
    return result;
}

WOW64 Key Transformation: GetWow64Key inserts Wow6432Node into the registry path to access the 32-bit view.

Sources: OfficeScrubC2R-Native.cs:349-363, OfficeScrubC2R-Native.cs:583-593

Pattern 3: Resource Disposal with Using Statements

All helpers use using statements or explicit disposal to prevent resource leaks:

// RegistryHelper
using (var key = OpenKey(GetHiveKey(hive), subKey, false))
{
    if (key != null)
    {
        foreach (var name in key.GetSubKeyNames())
            keys.Add(name);
    }
}

// ProcessHelper
finally
{
    process.Dispose();
}

Sources: OfficeScrubC2R-Native.cs:408-415, OfficeScrubC2R-Native.cs:804-807

Pattern 4: HashSet for Deduplication

Registry enumeration methods use HashSet<string> with case-insensitive comparison to automatically deduplicate entries from 32-bit and 64-bit views:

public string[] EnumerateKeys(RegistryHiveType hive, string subKey)
{
    var keys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
    
    // Enumerate regular view
    using (var key = OpenKey(GetHiveKey(hive), subKey, false))
    {
        if (key != null)
            foreach (var name in key.GetSubKeyNames())
                keys.Add(name);
    }
    
    // Enumerate WOW64 view (duplicates automatically ignored)
    if (_is64Bit)
    {
        using (var key = OpenKey(GetHiveKey(hive), GetWow64Key(subKey), false))
        {
            if (key != null)
                foreach (var name in key.GetSubKeyNames())
                    keys.Add(name);
        }
    }
    
    return keys.ToArray();
}

Performance benefit: O(1) lookup time vs O(n) for array-based deduplication.

Sources: OfficeScrubC2R-Native.cs:402-436

Pattern 5: Parallel Task Execution

ProcessHelper uses Task.Run for parallel operations with timeout management:

public List<int> TerminateProcesses(string[] processNames, int timeoutMs = 5000)
{
    var terminatedPids = new List<int>();
    var tasks = new List<Task>();
    
    foreach (var process in processes)
    {
        tasks.Add(Task.Run(() =>
        {
            try
            {
                if (!process.HasExited)
                {
                    process.Kill();
                    if (process.WaitForExit(timeoutMs))
                    {
                        lock (terminatedPids)  // Thread-safe list access
                        {
                            terminatedPids.Add(pid);
                        }
                    }
                }
            }
            finally
            {
                process.Dispose();
            }
        }));
    }
    
    Task.WaitAll(tasks.ToArray(), timeoutMs * 2);
    return terminatedPids;
}

Sources: OfficeScrubC2R-Native.cs:775-814


Dependency Relationships

The helper classes have minimal dependencies, with only two requiring other helpers:

graph LR
    subgraph "Independent Helpers"
        GuidHelper["GuidHelper<br/>Static utility"]
        RegistryHelper["RegistryHelper<br/>No dependencies"]
        FileHelper["FileHelper<br/>No dependencies"]
        ProcessHelper["ProcessHelper<br/>No dependencies"]
        ShellHelper["ShellHelper<br/>No dependencies"]
        LicenseHelper["LicenseHelper<br/>Uses FileHelper internally"]
        ServiceHelper["ServiceHelper<br/>No dependencies"]
    end
    
    subgraph "Dependent Helpers"
        WindowsInstallerHelper["WindowsInstallerHelper<br/>Requires RegistryHelper"]
        TypeLibHelper["TypeLibHelper<br/>Requires RegistryHelper"]
    end
    
    WindowsInstallerHelper --> RegistryHelper
    WindowsInstallerHelper --> GuidHelper
    TypeLibHelper --> RegistryHelper
    LicenseHelper --> FileHelper
Loading

Dependency Injection Pattern

Helpers requiring dependencies receive them via constructor parameters:

Helper Class Dependencies Injection Method
WindowsInstallerHelper RegistryHelper Constructor parameter OfficeScrubC2R-Native.cs:984-987
TypeLibHelper RegistryHelper Constructor parameter OfficeScrubC2R-Native.cs:1153-1156
LicenseHelper FileHelper Creates new instance internally OfficeScrubC2R-Native.cs:1264

All other helpers have no dependencies and can be instantiated directly.

Sources: OfficeScrubC2R-Native.cs:980-1273


Helper Class Summary Table

The following table provides a quick reference for all helper classes:

Class Type Static? Dependencies Primary Use Case Performance Gain
GuidHelper Utility ✓ Yes None GUID format conversion for MSI metadata N/A (pure conversion)
RegistryHelper Core No None WOW64-aware registry operations 30x vs. PowerShell
FileHelper Core No None File deletion with reboot scheduling 15x vs. PowerShell
ProcessHelper Core No None Parallel process termination 5-10x vs. sequential
ShellHelper UI No None Taskbar/Start menu cleanup N/A (no PS equivalent)
WindowsInstallerHelper Cleanup No RegistryHelper MSI metadata removal Batch operations
TypeLibHelper Cleanup No RegistryHelper COM TypeLib cleanup Batch operations
LicenseHelper Office No FileHelper (internal) License removal via WMI N/A (WMI-based)
ServiceHelper System No None Windows service management N/A (WMI-based)
OfficeScrubOrchestrator Facade No All helpers Unified interface Overall coordination

Sources: OfficeScrubC2R-Native.cs:17-1408, docs/memory-bank/product.md:1-62


For detailed documentation of each helper class's methods and implementation details, see the subsection pages: RegistryHelper, FileHelper, ProcessHelper, WindowsInstallerHelper, and Additional Helpers.

Clone this wiki locally