Repository navigation
Overview
Relevant source files
The following files were used as context for generating this wiki page:
OfficeScrubC2R is a PowerShell module that wraps a native C# library (OfficeScrubNative.dll) to perform deep cleanup of Microsoft Office Click-to-Run installations. The module serves as a replacement for Microsoft's legacy OffScrubC2R.vbs (v2.19) with 10-50x performance improvements through compiled code and direct Windows API access.
Office Click-to-Run installations occasionally fail to uninstall through standard Windows mechanisms (Programs and Features, ODT uninstall, or setup.exe /uninstall). When this occurs, residual registry keys, files, Windows Installer metadata, and COM registrations prevent clean reinstallation. OfficeScrubC2R provides forensic-level cleanup across eight Windows subsystems: Registry (HKLM/HKCU/HKCR with WOW64 support), File System (with locked file handling), Processes, Services, Windows Installer metadata, COM Type Libraries, Software Protection Platform (SPP/OSPP), and Shell Integration.
Microsoft's original VBScript solution (OffScrubC2R.vbs) suffers from performance limitations inherent to interpreted scripting and COM automation. The PowerShell/C# hybrid architecture achieves dramatic performance gains through:
-
Compiled C# Code: Native
OfficeScrubNative.dllreplaces interpreted VBScript -
Direct Win32 APIs: P/Invoke to
advapi32.dll,kernel32.dll,shell32.dllbypasses COM overhead -
Parallel Processing: Multi-threaded operations via
Task.Run()andTask.WaitAll() -
Optimized Data Structures:
HashSet<string>for O(1) lookups vs. linear array scans - Static Caching: Reduced repetitive API calls in registry enumeration
Sources: README.md:1-14, OfficeScrubC2R.psd1:24-26, docs/memory-bank/product.md:1-11
The system targets Office 2013, 2016, 2019, and Office 365 Click-to-Run installations on Windows 7 SP1 through Windows 11 (both x86 and x64 architectures).
| Subsystem | Implemented By | Key Operations |
|---|---|---|
| Registry | RegistryHelper |
Recursive key deletion across HKLM, HKCU, HKCR with WOW64 dual-path access (KEY_WOW64_64KEY, KEY_WOW64_32KEY) |
| File System | FileHelper |
Directory deletion with cmd.exe rd /s /q optimization; locked file handling via MoveFileEx(MOVEFILE_DELAY_UNTIL_REBOOT)
|
| Processes | ProcessHelper |
Parallel process termination via Task.Run(); GetProcessesUsingPath() for file lock detection |
| Windows Installer | WindowsInstallerHelper |
Product/Component/UpgradeCode cleanup using GUID transformation (GetExpandedGuid, GetCompressedGuid, GetDecodedGuid) |
| COM Type Libraries | TypeLibHelper |
Unregister type libraries from HKCR\TypeLib and HKCR\Interface
|
| SPP/OSPP Licensing | LicenseHelper |
Clear Office Software Protection Platform tokens (optional via -KeepLicense parameter) |
| Shell Integration | ShellHelper |
Remove published components, taskbar pins, start menu items using Shell.Application COM object |
| Services | ServiceHelper |
Delete Office-related Windows services via WMI |
Sources: docs/memory-bank/product.md:14-24, OfficeScrubC2R.psd1:58-64
OfficeScrubC2R implements a two-layer hybrid architecture: a PowerShell wrapper layer for user interaction and a native C# library for performance-critical operations.
graph TB
subgraph PowerShell["PowerShell Module Layer"]
PSM["OfficeScrubC2R.psm1"]
PSD1["OfficeScrubC2R.psd1"]
end
subgraph Native["Native C# Layer (OfficeScrubNative.dll)"]
ORCH["OfficeScrubOrchestrator"]
subgraph Helpers["Helper Classes"]
REG["RegistryHelper"]
FILE["FileHelper"]
PROC["ProcessHelper"]
WI["WindowsInstallerHelper"]
TL["TypeLibHelper"]
LIC["LicenseHelper"]
SVC["ServiceHelper"]
SH["ShellHelper"]
GUID["GuidHelper"]
end
end
subgraph Win32["Windows APIs"]
ADVAPI["advapi32.dll<br/>RegOpenKeyEx<br/>RegDeleteKeyEx"]
KERNEL["kernel32.dll<br/>MoveFileEx<br/>TerminateProcess"]
SHELL["shell32.dll<br/>Shell.Application"]
end
PSM --> ORCH
PSD1 --> PSM
ORCH --> REG
ORCH --> FILE
ORCH --> PROC
ORCH --> WI
ORCH --> TL
ORCH --> LIC
ORCH --> SVC
ORCH --> SH
ORCH --> GUID
REG --> ADVAPI
FILE --> KERNEL
PROC --> KERNEL
SH --> SHELL
The module OfficeScrubC2R.psm1:1-157 provides five exported functions:
-
Import-OfficeScrubNative- LoadsOfficeScrubNative.dllfrom the module directory -
New-OfficeScrubOrchestrator- Creates anOfficeScrubOrchestratorinstance with system bitness detection -
Test-OfficeC2RPath- Validates Click-to-Run installation paths -
Test-OfficeProductScope- Determines if a product code should be removed -
Get-OfficeScrubHelpers- Exposes helper class instances for direct use
OfficeScrubNative.dll contains the OfficeScrubOrchestrator class (central coordinator) and eight specialized helper classes. Each helper encapsulates operations for a specific Windows subsystem with direct P/Invoke to Win32 APIs. The GuidHelper class provides static utility methods for Windows Installer GUID transformations.
For detailed architecture documentation, see Architecture.
Sources: OfficeScrubC2R.psm1:1-157, OfficeScrubC2R.psd1:1-157, README.md:3-34, docs/memory-bank/guidelines.md:44-67
The native C# implementation delivers 10-50x performance gains over the original VBScript through five optimization strategies:
| Optimization | Implementation | Benefit |
|---|---|---|
| Compiled Code | C# compiled to MSIL vs. interpreted VBScript | Eliminates script parsing overhead |
| Direct Win32 APIs | P/Invoke to advapi32.dll, kernel32.dll vs. COM automation |
Removes COM marshaling layer |
| HashSet Collections |
HashSet<string> with StringComparer.OrdinalIgnoreCase
|
O(1) lookups vs. O(n) array scans |
| Parallel Processing |
Task.Run() for process termination |
Multi-core utilization |
| Optimized Algorithms |
cmd.exe rd /s /q for directories |
15x faster than recursive .NET deletion |
| Operation | VBScript Time | Native C# Time | Improvement |
|---|---|---|---|
| Registry enumeration (5000+ keys) | ~10 seconds | ~0.3 seconds | 30x |
| File deletion (large directories) | ~15 seconds | ~1 second | 15x |
| Complete Office removal | 5-10 minutes | 30-60 seconds | 10-50x |
For detailed performance architecture, see Performance Architecture.
Sources: docs/memory-bank/product.md:8-11, README.md:1-4
The PowerShell Gallery package contains six primary files:
| File | Purpose | Key Contents |
|---|---|---|
OfficeScrubC2R.psd1 |
Module manifest | Metadata, version 3.0.0, FunctionsToExport, FileList, PowerShell Gallery tags |
OfficeScrubC2R.psm1 |
Root module | Five exported functions, DLL loading logic |
OfficeScrubNative.dll |
Compiled native library |
OfficeScrubOrchestrator class, 8 helper classes, GuidHelper static class |
OfficeScrubC2R-Native.cs |
C# source code | Reference implementation for OfficeScrubNative.dll (3,803 lines) |
direct_conversion.cs |
Legacy reference | Direct VBScript-to-C# conversion showing implementation lineage |
docs/source/OfficeScrubC2R.vbs |
Original VBScript | Microsoft's original implementation (v2.19) |
The OfficeScrubNative.dll is pre-compiled for .NET Framework 4.5+ using csc.exe. A separate .NET Core 7+ build exists for PowerShell 7 compatibility. The build script build.ps1 handles compilation for both targets.
Sources: OfficeScrubC2R.psd1:82-91, README.md:5-13, README.md:47-66
The system implements a three-stage cleanup pipeline. The PowerShell module orchestrates workflow and logging while delegating performance-critical operations to the native C# library.
flowchart TD
Start["Import-Module<br/>OfficeScrubC2R"] --> Load["Import-OfficeScrubNative"]
Load --> Create["New-OfficeScrubOrchestrator"]
Create --> Detect["Detection Phase<br/>Test-OfficeC2RPath<br/>Test-OfficeProductScope"]
Detect --> Stage1["Stage 1: Uninstall<br/>- OSPP License Clear<br/>- Process Termination<br/>- ODT/MSI Uninstall"]
Stage1 --> Stage2["Stage 2: Registry Cleanup<br/>- RegistryHelper.DeleteKey()<br/>- WOW64 dual-path access<br/>- MSI metadata removal"]
Stage2 --> Stage3["Stage 3: File System Cleanup<br/>- FileHelper.DeleteDirectory()<br/>- Service deletion<br/>- MoveFileEx() for locked files"]
Stage3 --> Reboot{Pending<br/>Reboot?}
Reboot -->|Yes| Schedule["PendingFileRenameOperations<br/>Registry Entry"]
Reboot -->|No| Exit["Exit"]
Schedule --> Exit
-
Stage 1 (Uninstall): Clears SPP licenses via
LicenseHelper, terminates processes viaProcessHelper.TerminateProcesses(), attempts graceful uninstall via ODTConfiguration.xmlormsiexec.exe -
Stage 2 (Registry): Removes registry keys via
RegistryHelperwith recursive deletion and WOW64 support, cleans Windows Installer metadata viaWindowsInstallerHelper -
Stage 3 (File System): Deletes installation directories via
FileHelper.DeleteDirectory()withcmd.exe rd /s /qoptimization, schedules locked files viaMoveFileEx(MOVEFILE_DELAY_UNTIL_REBOOT)
For detailed pipeline documentation, see Three-Stage Execution Pipeline.
Sources: README.md:18-34, docs/memory-bank/product.md:14-24
| Component | Minimum Version | Notes |
|---|---|---|
| Windows | 7 SP1 | Windows 10/11 recommended |
| PowerShell | 5.1 | Compatible with PowerShell Core 7+ |
| .NET Framework | 4.5 | Required for OfficeScrubNative.dll (Windows PowerShell) |
| .NET SDK | 7.0 | Required for PowerShell Core compilation |
| Privileges | Administrator | Mandatory for registry and file operations |
| Architecture | x86, x64 | WOW64 registry redirection automatically handled |
The module supports both Windows PowerShell 5.1 (Desktop edition) and PowerShell Core 7+ (Core edition). The native DLL has two compilation targets:
-
.NET Framework 4.5- Used by Windows PowerShell 5.1 -
.NET 7.0- Used by PowerShell Core 7+
The Import-OfficeScrubNative function automatically selects the appropriate DLL based on the PowerShell edition ($PSVersionTable.PSEdition).
Sources: OfficeScrubC2R.psd1:9, OfficeScrubC2R.psd1:29-32, README.md:52-66, docs/memory-bank/product.md:58-64
The current release (v2.19.2) addresses a critical packaging issue in v2.19.1 where the main script file OfficeScrubC2R.ps1 was not included in the PowerShell Gallery package due to an incomplete FileList in the module manifest. This resulted in a non-functional module. Version 2.19.2 corrects the FileList to include all required script files.
Critical fix from v2.19.1 (also in v2.19.2): The Initialize-Environment function now executes automatically on module import, ensuring the $script:LogDir variable and OfficeScrubOrchestrator instance are properly initialized before any operations begin. This resolves null reference errors that occurred when functions like Test-IsC2R were called before manual environment initialization.
Sources: docs/CHANGELOG.md:8-33
Version 2.2.0 introduced the optimization strategies that achieve 10-50x performance improvements: Span<char> usage for memory efficiency, HashSet-based collections for O(1) lookups, static caching in registry operations, parallel processing for independent tasks, and StringComparison.OrdinalIgnoreCase for faster string comparisons.
Sources: docs/CHANGELOG.md:44-103
For detailed usage instructions and parameters, see User Guide.
For architectural deep-dives into each component, see Architecture.
For development and contribution guidelines, see Developer Guide.