Repository navigation
Helper Classes
Relevant source files
The following files were used as context for generating this wiki page:
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.
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
Sources: OfficeScrubC2R-Native.cs:17-1408
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
The nine helper classes can be logically grouped into four categories based on their operational domain:
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"]
Sources: OfficeScrubC2R-Native.cs:334-858
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"]
Sources: OfficeScrubC2R-Native.cs:980-1209
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"]
Sources: OfficeScrubC2R-Native.cs:1215-1343, docs/memory-bank/product.md:1-62
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"]
Sources: OfficeScrubC2R-Native.cs:171-328, OfficeScrubC2R-Native.cs:864-974
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
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:
- Property-based access: Each helper is exposed as a public property rather than through methods, simplifying PowerShell interop
-
Constructor injection:
WindowsInstallerHelperandTypeLibHelperreceiveRegistryHelperdependency in constructor -
64-bit awareness: Only
RegistryHelperneedsis64Bitparameter; file system automatically handles architecture - Single instantiation: Each helper is instantiated once per orchestrator lifetime
Sources: OfficeScrubC2R-Native.cs:1349-1407
All helper classes follow consistent design patterns to ensure reliability and performance:
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
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
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
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
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
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
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
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.