mirror of
https://github.com/tw93/Mole.git
synced 2026-02-15 07:00:05 +00:00
refactor(windows): fix cmdlet shadowing and enforce dependency isolation
This commit is contained in:
@@ -23,18 +23,18 @@ function Clear-SystemTempFiles {
|
||||
.SYNOPSIS
|
||||
Clean system-level temporary files (requires admin)
|
||||
#>
|
||||
|
||||
|
||||
if (-not (Test-IsAdmin)) {
|
||||
Write-Debug "Skipping system temp cleanup - requires admin"
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
# Windows Temp folder
|
||||
$winTemp = "$env:WINDIR\Temp"
|
||||
if (Test-Path $winTemp) {
|
||||
Remove-OldFiles -Path $winTemp -DaysOld 7 -Description "Windows temp files"
|
||||
}
|
||||
|
||||
|
||||
# System temp (different from Windows temp)
|
||||
$systemTemp = "$env:SYSTEMROOT\Temp"
|
||||
if ((Test-Path $systemTemp) -and ($systemTemp -ne $winTemp)) {
|
||||
@@ -52,12 +52,12 @@ function Clear-WindowsLogs {
|
||||
Clean Windows log files (requires admin)
|
||||
#>
|
||||
param([int]$DaysOld = 7)
|
||||
|
||||
|
||||
if (-not (Test-IsAdmin)) {
|
||||
Write-Debug "Skipping Windows logs cleanup - requires admin"
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
# Windows Logs directory
|
||||
$logPaths = @(
|
||||
"$env:WINDIR\Logs\CBS"
|
||||
@@ -71,13 +71,13 @@ function Clear-WindowsLogs {
|
||||
"$env:PROGRAMDATA\Microsoft\Windows\WER\ReportQueue"
|
||||
"$env:PROGRAMDATA\Microsoft\Windows\WER\ReportArchive"
|
||||
)
|
||||
|
||||
|
||||
foreach ($path in $logPaths) {
|
||||
if (Test-Path $path) {
|
||||
Remove-OldFiles -Path $path -DaysOld $DaysOld -Description "$(Split-Path -Leaf $path) logs"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Setup logs (*.log files in Windows directory)
|
||||
$setupLogs = Get-ChildItem -Path "$env:WINDIR\*.log" -File -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$DaysOld) }
|
||||
@@ -96,22 +96,22 @@ function Clear-WindowsUpdateFiles {
|
||||
.SYNOPSIS
|
||||
Clean Windows Update download cache (requires admin)
|
||||
#>
|
||||
|
||||
|
||||
if (-not (Test-IsAdmin)) {
|
||||
Write-Debug "Skipping Windows Update cleanup - requires admin"
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
# Stop Windows Update service
|
||||
$wuService = Get-Service -Name wuauserv -ErrorAction SilentlyContinue
|
||||
$wasRunning = $wuService.Status -eq 'Running'
|
||||
|
||||
|
||||
if ($wasRunning) {
|
||||
if (Test-DryRunMode) {
|
||||
Write-DryRun "Windows Update cache (service would be restarted)"
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Stop-Service -Name wuauserv -Force -ErrorAction Stop
|
||||
}
|
||||
@@ -120,14 +120,14 @@ function Clear-WindowsUpdateFiles {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
# Clean download cache
|
||||
$wuDownloadPath = "$env:WINDIR\SoftwareDistribution\Download"
|
||||
if (Test-Path $wuDownloadPath) {
|
||||
Clear-DirectoryContents -Path $wuDownloadPath -Description "Windows Update download cache"
|
||||
}
|
||||
|
||||
|
||||
# Clean DataStore (old update history - be careful!)
|
||||
# Only clean temp files, not the actual database
|
||||
$wuDataStore = "$env:WINDIR\SoftwareDistribution\DataStore\Logs"
|
||||
@@ -152,15 +152,15 @@ function Clear-InstallerCache {
|
||||
.SYNOPSIS
|
||||
Clean Windows Installer cache (orphaned patches)
|
||||
#>
|
||||
|
||||
|
||||
if (-not (Test-IsAdmin)) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
# Windows Installer patch cache
|
||||
# WARNING: Be very careful here - only clean truly orphaned files
|
||||
$installerPath = "$env:WINDIR\Installer"
|
||||
|
||||
|
||||
# Only clean .tmp files and very old .msp files that are likely orphaned
|
||||
if (Test-Path $installerPath) {
|
||||
$tmpFiles = Get-ChildItem -Path $installerPath -Filter "*.tmp" -File -ErrorAction SilentlyContinue
|
||||
@@ -169,7 +169,7 @@ function Clear-InstallerCache {
|
||||
Remove-SafeItems -Paths $paths -Description "Installer temp files"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Installer logs in temp
|
||||
$installerLogs = Get-ChildItem -Path $env:TEMP -Filter "MSI*.LOG" -File -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) }
|
||||
@@ -188,26 +188,26 @@ function Invoke-ComponentStoreCleanup {
|
||||
.SYNOPSIS
|
||||
Run Windows Component Store cleanup (DISM)
|
||||
#>
|
||||
|
||||
|
||||
if (-not (Test-IsAdmin)) {
|
||||
Write-Debug "Skipping component store cleanup - requires admin"
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (Test-DryRunMode) {
|
||||
Write-DryRun "Component Store cleanup (DISM)"
|
||||
Set-SectionActivity
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Write-Info "Running Component Store cleanup (this may take a while)..."
|
||||
|
||||
|
||||
# Run DISM cleanup
|
||||
$result = Start-Process -FilePath "dism.exe" `
|
||||
-ArgumentList "/Online", "/Cleanup-Image", "/StartComponentCleanup" `
|
||||
-Wait -PassThru -NoNewWindow -ErrorAction Stop
|
||||
|
||||
|
||||
if ($result.ExitCode -eq 0) {
|
||||
Write-Success "Component Store cleanup"
|
||||
Set-SectionActivity
|
||||
@@ -230,13 +230,13 @@ function Clear-MemoryDumps {
|
||||
.SYNOPSIS
|
||||
Clean Windows memory dumps
|
||||
#>
|
||||
|
||||
|
||||
$dumpPaths = @(
|
||||
"$env:WINDIR\MEMORY.DMP"
|
||||
"$env:WINDIR\Minidump"
|
||||
"$env:LOCALAPPDATA\CrashDumps"
|
||||
)
|
||||
|
||||
|
||||
foreach ($path in $dumpPaths) {
|
||||
if (Test-Path $path -PathType Leaf) {
|
||||
# Single file (MEMORY.DMP)
|
||||
@@ -258,29 +258,29 @@ function Clear-SystemFontCache {
|
||||
.SYNOPSIS
|
||||
Clear Windows font cache (requires admin and may need restart)
|
||||
#>
|
||||
|
||||
|
||||
if (-not (Test-IsAdmin)) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
$fontCacheService = Get-Service -Name "FontCache" -ErrorAction SilentlyContinue
|
||||
|
||||
|
||||
if ($fontCacheService) {
|
||||
if (Test-DryRunMode) {
|
||||
Write-DryRun "System font cache"
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
# Stop font cache service
|
||||
Stop-Service -Name "FontCache" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
|
||||
# Clear font cache files
|
||||
$fontCachePath = "$env:WINDIR\ServiceProfiles\LocalService\AppData\Local\FontCache"
|
||||
if (Test-Path $fontCachePath) {
|
||||
Clear-DirectoryContents -Path $fontCachePath -Description "System font cache"
|
||||
}
|
||||
|
||||
|
||||
# Restart font cache service
|
||||
Start-Service -Name "FontCache" -ErrorAction SilentlyContinue
|
||||
}
|
||||
@@ -301,19 +301,19 @@ function Invoke-DiskCleanupTool {
|
||||
Run Windows built-in Disk Cleanup tool with predefined settings
|
||||
#>
|
||||
param([switch]$Full)
|
||||
|
||||
|
||||
if (-not (Test-IsAdmin)) {
|
||||
Write-Debug "Skipping Disk Cleanup tool - requires admin for full cleanup"
|
||||
}
|
||||
|
||||
|
||||
if (Test-DryRunMode) {
|
||||
Write-DryRun "Windows Disk Cleanup tool"
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
# Set up registry keys for automated cleanup
|
||||
$cleanupKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches"
|
||||
|
||||
|
||||
$cleanupItems = @(
|
||||
"Active Setup Temp Folders"
|
||||
"Downloaded Program Files"
|
||||
@@ -331,7 +331,7 @@ function Invoke-DiskCleanupTool {
|
||||
"Windows Error Reporting System Archive Files"
|
||||
"Windows Error Reporting System Queue Files"
|
||||
)
|
||||
|
||||
|
||||
if ($Full -and (Test-IsAdmin)) {
|
||||
$cleanupItems += @(
|
||||
"Previous Installations"
|
||||
@@ -341,7 +341,7 @@ function Invoke-DiskCleanupTool {
|
||||
"Windows Upgrade Log Files"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
# Enable cleanup items in registry
|
||||
foreach ($item in $cleanupItems) {
|
||||
$itemPath = Join-Path $cleanupKey $item
|
||||
@@ -349,13 +349,13 @@ function Invoke-DiskCleanupTool {
|
||||
Set-ItemProperty -Path $itemPath -Name "StateFlags0100" -Value 2 -Type DWord -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
# Run disk cleanup
|
||||
$process = Start-Process -FilePath "cleanmgr.exe" `
|
||||
-ArgumentList "/sagerun:100" `
|
||||
-Wait -PassThru -NoNewWindow -ErrorAction Stop
|
||||
|
||||
|
||||
if ($process.ExitCode -eq 0) {
|
||||
Write-Success "Windows Disk Cleanup"
|
||||
Set-SectionActivity
|
||||
@@ -379,41 +379,41 @@ function Invoke-SystemCleanup {
|
||||
[switch]$IncludeComponentStore,
|
||||
[switch]$IncludeDiskCleanup
|
||||
)
|
||||
|
||||
|
||||
Start-Section "System cleanup"
|
||||
|
||||
|
||||
if (-not (Test-IsAdmin)) {
|
||||
Write-Warning "Running without admin - some cleanup tasks will be skipped"
|
||||
Write-MoleWarning "Running without admin - some cleanup tasks will be skipped"
|
||||
}
|
||||
|
||||
|
||||
# System temp files
|
||||
Clear-SystemTempFiles
|
||||
|
||||
|
||||
# Windows logs
|
||||
Clear-WindowsLogs -DaysOld 7
|
||||
|
||||
|
||||
# Windows Update cache
|
||||
Clear-WindowsUpdateFiles
|
||||
|
||||
|
||||
# Installer cache
|
||||
Clear-InstallerCache
|
||||
|
||||
|
||||
# Memory dumps
|
||||
Clear-MemoryDumps
|
||||
|
||||
|
||||
# Font cache
|
||||
Clear-SystemFontCache
|
||||
|
||||
|
||||
# Optional: Component Store (can take a long time)
|
||||
if ($IncludeComponentStore) {
|
||||
Invoke-ComponentStoreCleanup
|
||||
}
|
||||
|
||||
|
||||
# Optional: Windows Disk Cleanup tool
|
||||
if ($IncludeDiskCleanup) {
|
||||
Invoke-DiskCleanupTool -Full
|
||||
}
|
||||
|
||||
|
||||
Stop-Section
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Prevent multiple sourcing
|
||||
if ((Get-Variable -Name 'MOLE_COMMON_LOADED' -Scope Script -ErrorAction SilentlyContinue) -and $script:MOLE_COMMON_LOADED) {
|
||||
return
|
||||
if ((Get-Variable -Name 'MOLE_COMMON_LOADED' -Scope Script -ErrorAction SilentlyContinue) -and $script:MOLE_COMMON_LOADED) {
|
||||
return
|
||||
}
|
||||
$script:MOLE_COMMON_LOADED = $true
|
||||
|
||||
@@ -61,18 +61,18 @@ function Initialize-Mole {
|
||||
.SYNOPSIS
|
||||
Initialize Mole environment
|
||||
#>
|
||||
|
||||
|
||||
# Ensure config directory exists
|
||||
$configPath = Get-ConfigPath
|
||||
|
||||
|
||||
# Ensure cache directory exists
|
||||
$cachePath = Get-CachePath
|
||||
|
||||
|
||||
# Set up cleanup trap
|
||||
$null = Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {
|
||||
Clear-TempFiles
|
||||
}
|
||||
|
||||
|
||||
Write-Debug "Mole initialized"
|
||||
Write-Debug "Config: $configPath"
|
||||
Write-Debug "Cache: $cachePath"
|
||||
@@ -90,8 +90,8 @@ function Request-AdminPrivileges {
|
||||
Restarts the script with elevated privileges using UAC
|
||||
#>
|
||||
if (-not (Test-IsAdmin)) {
|
||||
Write-Warning "Some operations require administrator privileges."
|
||||
|
||||
Write-MoleWarning "Some operations require administrator privileges."
|
||||
|
||||
if (Read-Confirmation -Prompt "Restart with admin privileges?" -Default $true) {
|
||||
$scriptPath = $MyInvocation.PSCommandPath
|
||||
if ($scriptPath) {
|
||||
@@ -113,7 +113,7 @@ function Invoke-AsAdmin {
|
||||
[Parameter(Mandatory)]
|
||||
[scriptblock]$ScriptBlock
|
||||
)
|
||||
|
||||
|
||||
if (Test-IsAdmin) {
|
||||
& $ScriptBlock
|
||||
}
|
||||
@@ -126,5 +126,5 @@ function Invoke-AsAdmin {
|
||||
# ============================================================================
|
||||
# Exports (functions are available via dot-sourcing)
|
||||
# ============================================================================
|
||||
# All functions from base.ps1, log.ps1, file_ops.ps1, and ui.ps1 are
|
||||
# All functions from base.ps1, log.ps1, file_ops.ps1, and ui.ps1 are
|
||||
# automatically available when this file is dot-sourced.
|
||||
|
||||
@@ -37,16 +37,16 @@ function Write-LogMessage {
|
||||
[string]$Color,
|
||||
[string]$Icon
|
||||
)
|
||||
|
||||
|
||||
$timestamp = Get-Date -Format "HH:mm:ss"
|
||||
$colorCode = $script:Colors[$Color]
|
||||
$nc = $script:Colors.NC
|
||||
|
||||
|
||||
$formattedIcon = if ($Icon) { "$Icon " } else { "" }
|
||||
$output = " ${colorCode}${formattedIcon}${nc}${Message}"
|
||||
|
||||
|
||||
Write-Host $output
|
||||
|
||||
|
||||
# Also write to log file if configured
|
||||
if ($script:LogConfig.LogFile) {
|
||||
"$timestamp [$Level] $Message" | Out-File -Append -FilePath $script:LogConfig.LogFile -Encoding UTF8
|
||||
@@ -71,7 +71,8 @@ function Write-Success {
|
||||
Write-LogMessage -Message $Message -Level "SUCCESS" -Color "Green" -Icon $script:Icons.Success
|
||||
}
|
||||
|
||||
function Write-Warning {
|
||||
|
||||
function Write-MoleWarning {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Write a warning message
|
||||
@@ -80,7 +81,7 @@ function Write-Warning {
|
||||
Write-LogMessage -Message $Message -Level "WARN" -Color "Yellow" -Icon $script:Icons.Warning
|
||||
}
|
||||
|
||||
function Write-Error {
|
||||
function Write-MoleError {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Write an error message
|
||||
@@ -89,13 +90,14 @@ function Write-Error {
|
||||
Write-LogMessage -Message $Message -Level "ERROR" -Color "Red" -Icon $script:Icons.Error
|
||||
}
|
||||
|
||||
|
||||
function Write-Debug {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Write a debug message (only if debug mode is enabled)
|
||||
#>
|
||||
param([string]$Message)
|
||||
|
||||
|
||||
if ($script:LogConfig.DebugEnabled) {
|
||||
$gray = $script:Colors.Gray
|
||||
$nc = $script:Colors.NC
|
||||
@@ -128,15 +130,15 @@ function Start-Section {
|
||||
Start a new section with a title
|
||||
#>
|
||||
param([string]$Title)
|
||||
|
||||
|
||||
$script:CurrentSection.Active = $true
|
||||
$script:CurrentSection.Activity = $false
|
||||
$script:CurrentSection.Name = $Title
|
||||
|
||||
|
||||
$purple = $script:Colors.PurpleBold
|
||||
$nc = $script:Colors.NC
|
||||
$arrow = $script:Icons.Arrow
|
||||
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "${purple}${arrow} ${Title}${nc}"
|
||||
}
|
||||
@@ -176,11 +178,11 @@ function Start-Spinner {
|
||||
Start an inline spinner with message
|
||||
#>
|
||||
param([string]$Message = "Working...")
|
||||
|
||||
|
||||
$script:SpinnerIndex = 0
|
||||
$gray = $script:Colors.Gray
|
||||
$nc = $script:Colors.NC
|
||||
|
||||
|
||||
Write-Host -NoNewline " ${gray}$($script:SpinnerFrames[0]) $Message${nc}"
|
||||
}
|
||||
|
||||
@@ -190,12 +192,12 @@ function Update-Spinner {
|
||||
Update the spinner animation
|
||||
#>
|
||||
param([string]$Message)
|
||||
|
||||
|
||||
$script:SpinnerIndex = ($script:SpinnerIndex + 1) % $script:SpinnerFrames.Count
|
||||
$frame = $script:SpinnerFrames[$script:SpinnerIndex]
|
||||
$gray = $script:Colors.Gray
|
||||
$nc = $script:Colors.NC
|
||||
|
||||
|
||||
# Move cursor to beginning of line and clear
|
||||
Write-Host -NoNewline "`r ${gray}$frame $Message${nc} "
|
||||
}
|
||||
@@ -223,15 +225,15 @@ function Write-Progress {
|
||||
[string]$Message = "",
|
||||
[int]$Width = 30
|
||||
)
|
||||
|
||||
|
||||
$percent = if ($Total -gt 0) { [Math]::Round(($Current / $Total) * 100) } else { 0 }
|
||||
$filled = [Math]::Round(($Width * $Current) / [Math]::Max($Total, 1))
|
||||
$empty = $Width - $filled
|
||||
|
||||
|
||||
$bar = ("[" + ("=" * $filled) + (" " * $empty) + "]")
|
||||
$cyan = $script:Colors.Cyan
|
||||
$nc = $script:Colors.NC
|
||||
|
||||
|
||||
Write-Host -NoNewline "`r ${cyan}$bar${nc} ${percent}% $Message "
|
||||
}
|
||||
|
||||
@@ -253,7 +255,7 @@ function Set-LogFile {
|
||||
Set a log file for persistent logging
|
||||
#>
|
||||
param([string]$Path)
|
||||
|
||||
|
||||
$script:LogConfig.LogFile = $Path
|
||||
$dir = Split-Path -Parent $Path
|
||||
if ($dir -and -not (Test-Path $dir)) {
|
||||
|
||||
Reference in New Issue
Block a user