
# When deleting temp files en masse, only delete files/folders older than the number of days specified here
$OlderThan = 7
$TimeDelta = New-TimeSpan -Days $OlderThan

# Remove all *.evtx files from system temporary files location
$EventLogs = Get-ChildItem -Path "${Env:SystemRoot}\TEMP\*" -File -Filter *.evtx
If ( $EventLogs ) {
    LogMsg "Deleting all event logs from ${Env:SystemRoot}\TEMP"
    ForEach ( $EventLog in $EventLogs ) { Remove-Item $EventLog -Force -ErrorAction SilentlyContinue }
}

# Remove misc logs and error reports
$MiscLogs = Get-ChildItem -Path "${Env:SystemRoot}\TEMP\*" -File -Include "${Env:COMPUTERNAME}-*.log", "AppxErrorReport_*.txt"
If ( $MiscLogs ) {
    LogMsg "Deleting misc logs from ${Env:SystemRoot}\TEMP"
    ForEach ( $MiscLog in $MiscLogs ) { Remove-Item $MiscLog -Force -ErrorAction SilentlyContinue }
}

# Remove archived CBS logs
$CBSLogs = Get-ChildItem -Path "${Env:SystemRoot}\Logs\CBS\*" -File -Include "CbsPersist_*.log", "CbsPersist_*.cab"
If ( $CBSLogs ) {
    $TotalBytes = 0
    ForEach ( $CBSLog in $CBSLogs) { $TotalBytes += $CBSLog.Length }
    $TotalSize = [math]::Round(($TotalBytes / 1MB),2)
    If ( $TotalSize -ge 200 ) {
        LogMsg "Total CBS log archive size: ${TotalSize}MB"
        Control-Service -Stop 'TrustedInstaller'
        LogMsg "Deleting primary CBS.log file"
        Remove-Item "${Env:SystemRoot}\Logs\CBS\CBS.log" -Force -ErrorAction SilentlyContinue
        Control-Service -Start 'TrustedInstaller'
    }
    LogMsg "Deleting archived CBS logs from ${Env:SystemRoot}\Logs\CBS"
    ForEach ( $CBSLog in $CBSLogs ) { Remove-Item $CBSLog -Force -ErrorAction SilentlyContinue }
}

# Remove all system temp files older than 7 days
$OldTempFiles = Get-ChildItem -Path "${Env:SystemRoot}\TEMP" | Where { $_.LastWriteTime -lt ((Get-Date) - $TimeDelta) }
If ( $OldTempFiles ) {
    LogMsg "Deleting all temp files not modified in ${OlderThan} day(s) from ${Env:SystemRoot}\TEMP"
    ForEach ( $OldTempFile in $OldTempFiles ) { Remove-Item $OldTempFile -Force -Recurse -ErrorAction SilentlyContinue }
}

# Remove all old files from the Recycle Bin
$RecycleBin = (New-Object -ComObject Shell.Application).NameSpace(0xa)
ForEach($file in $RecycleBin.Items()) {

    # Remove RTL and LTR marks from date string so it can be compared
    $DateDeleted = $Recycler.GetDetailsOf($item,2) -replace "\u200f|\u200e",""

    # Make sure the item has expired
    If( (Get-Date $DateDeleted) -lt ((Get-Date) - $TimeDelta)) {

        # Delete the item
        $path = $file.Path
        Write-Output "Deleting expired Recycle Bin item: ""${path}"""
        Try { Remove-Item -Path $path -Force -Recurse }
        Catch { Write-Error $_.Exception.Message }
    }
}

# Turn off system hibernation if it's in use
If ( Test-Path "${Env:SystemDrive}\hiberfil.sys" ) {
    LogMsg "Turning off system hibernation"
    Try { Start-Process "powercfg" -ArgumentList "-h off" -Wait }
    Catch { LogErr $_.Exception.Message }
}

# Remove PDCRevocation dump files
$PDCRevocationDumpFiles = Get-ChildItem -Path "${Env:SystemRoot}\LiveKernelReports\*" -File -Include "PDCRevocation-*.dmp"
If ( $PDCRevocationDumpFiles ) {
    LogMsg "Deleting PDCRevocation dump files from ${Env:SystemRoot}\LiveKernelReports"
    ForEach ( $PDCRevocationDump in $PDCRevocationDumpFiles ) { Remove-Item $PDCRevocationDump -Force -ErrorAction SilentlyContinue }
}

# Remove Genetec application crash dumps
If ( Test-Path "${Env:ProgramData}\Genetec\Dumps" ) {
    $GenetecCrashDumps = Get-ChildItem -Path "${Env:ProgramData}\Genetec\Dumps"
    If ( $GenetecCrashDumps )
    {
        LogMsg "Deleting Genetec application crash dumps"
        Try { ForEach ( $dump in $GenetecCrashDumps ) { Remove-Item $dump.FullName -Force -Recurse -ErrorAction SilentlyContinue } }
        Catch { LogErr $_.Exception.Message }
    }
}

# Defragment Windows Elastic Search database
$ESDB = "${Env:ProgramData}\Microsoft\Search\Data\Applications\Windows\Windows.edb"
If ( Test-Path $ESDB ) {
    Try {
        LogMsg "Found Windows Elastic Search database: ""${ESDB}"""
        LogMsg "  - Disabling Windows Search service"
        Start-Process "sc.exe" -ArgumentList "config wsearch start= disabled" -Wait
        LogMsg "  - Stopping Windows Search Service"
        Start-Process "net.exe" -ArgumentList "stop wsearch" -Wait
        LogMsg "  - Defragmenting database file"
        Start-Process "esentutl.exe" -ArgumentList "/d ""${ESDB}""" -Wait
        LogMsg "  - Enabling Windows Search Service"
        Start-Process "sc.exe" -ArgumentList "config wsearch start= delayed-auto" -Wait
        LogMsg "  - Starting Windows Search Service"
        Start-Process "net.exe" -ArgumentList "start wsearch" -Wait
    }
    Catch { LogErr $_.Exception.Message }

}

# Remove any Autodesk installers at their default location
$ADSKInst = "${Env:SystemDrive}\Autodesk"
If ( Test-Path $ADSKInst ) {
    $foldersToDelete = Get-ChildItem -Path $ADKSInst -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer) -and ($_.LastWriteTime -lt ((Get-Date) - $TimeDelta)) -and ( $_.Name -ne "WI") }
    ForEach ( $folder in $foldersToDelete ) {
        $path = $folder.FullName
        LogMsg "Deleting Autodesk installer directory: ""${path}"""
        Try { Remove-Item $folder -Force -Recurse -ErrorAction SilentlyContinue }
        Catch { LogErr $_.Exception.Message }
    }
}

# TODO: Evaluate system restore points and delete them if they take up too much space

# Remove files from user profile directories
ForEach ( $userProfile in $(EnumUserProfiles) ) {

    # Remove all user temp files older than 7 days
    $OldTempFiles = Get-ChildItem -Path "${userProfile}\AppData\Local\Temp" -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt ((Get-Date) - $TimeDelta) }
    If ( $OldTempFiles ) {
        LogMsg "Deleting all temp files not modified in ${OlderThan} day(s) from ""${userProfile}\AppData\Local\Temp"""
        ForEach ( $OldTempFile in $OldTempFiles ) { Remove-Item $OldTempFile -Force -Recurse -ErrorAction SilentlyContinue }
    }

    # Remove AutoCAD temp files
    If (-not (IsRunning -Name "acad") ) {
        $AutoCADTempFiles = Get-ChildItem -Path "${userProfile}\AppData\Local\Temp\*" -File -Include '*.ac$' -ErrorAction SilentlyContinue
        If ( $AutoCADTempFiles ) {
            LogMsg "Deleting AutoCAD temp files"
            ForEach ( $tempfile in $AutoCADTempFiles ) {
                Try { Remove-Item $tempfile -Force -ErrorAction SilentlyContinue }
                Catch { LogErr $_.Exception.Message }
            }
        }
    }

    # Apple iTunes data
    # If (-not (IsRunning -Name 'itunes') ) {

    #     # Remove Apple software updates downloaded from iTunes
    #     $IPSWBasePath = "${userProfile}\AppData\Roaming\Apple Computer\iTunes"
    #     $IPSW = @()
    #     # iPhone update files
    #     ForEach ( $updateFile in $(Get-ChildItem -Path "${IPSWBasePath}\iPhone Software Updates\*" -File -Include '*.ipsw' -ErrorAction SilentlyContinue) ) {
    #         $IPSW += ,@($updateFile.FullName)
    #     }
    #     # iPad update files
    #     ForEach ( $updateFile in $(Get-ChildItem -Path "${IPSWBasePath}\iPad Software Updates\*" -File -Include '*.ipsw' -ErrorAction SilentlyContinue) ) {
    #         $IPSW += ,@($updateFile.FullName)
    #     }
    #     # iPod update files
    #     ForEach ( $updateFile in $(Get-ChildItem -Path "${IPSWBasePath}\iPod Software Updates\*" -File -Include '*.ipsw' -ErrorAction SilentlyContinue) ) {
    #         $IPSW += ,@($updateFile.FullName)
    #     }

    #     # Remove Apple mobile applications downloaded from iTunes
    #     $IPA = @()
    #     ForEach ( $mobileApp in $(Get-ChildItem -Path "${userProfile}\Music\iTunes\iTunes Media\Mobile Applications\*" -File -Include '*.ipa' -ErrorAction SilentlyContinue) ) {
    #         $IPA += ,@($updateFile.FullName)
    #     }
    
    #     If ( $IPSW ) {
    #         LogMsg "Found Apple software update files"
    #         ForEach ( $path in $IPSW ) {
    #             LogMsg "  - Deleting: ""${path}"""
    #             Try { Remove-Item -Path $path -Force -ErrorAction SilentlyContinue }
    #             Catch { LogErr $_.Exception.Message }
    #         }
    #     }

    #     If ( $IPA ) {
    #         LogMsg "Found Apple mobile application files"
    #         ForEach ( $path in $IPA ) {
    #             LogMsg "  - Deleting: ""${path}"""
    #             Try { Remove-Item -Path $path -Force -ErrorAction SilentlyContinue }
    #             Catch { LogErr $_.Exception.Message }
    #         }
    #     }
    # }
    
    # Remove old downloaded application files
    $OldDownloadedApps = (Get-ChildItem -Path "${userProfile}\Downloads\*" -File -Filter '*.exe' -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt ((Get-Date) - $TimeDelta) })
    If ( $OldDownloadedApps ) {
        LogMsg "Deleting old downloaded app files"
        ForEach ( $oldDownloadedApp in $OldDownloadedApps ) {
            $path = $oldDownloadedApp.FullName
            LogMsg "  - Deleting: ""${path}"""
            Try { Remove-Item -Path $path -Force -ErrorAction SilentlyContinue }
            Catch { LogErr $_.Exception.Message }
        }
    }
    
    # Remove duplicate downloads
    # Separate the possible duplicates from the rest
    $PossibleDuplicates = @()
    $NotDuplicates = @()
    ForEach ( $file in (Get-ChildItem -Path "${userProfile}\Downloads\*" -File -ErrorAction SilentlyContinue) ) {
        If ( $file.BaseName -match '\s\(\d*\)$' ) {
            $PossibleDuplicates += ,@($file)
        } Else {
            $NotDuplicates += ,@($file)
        }
    }
    # Loop through all files
    ForEach ( $pd in $PossibleDuplicates ) {
        ForEach ( $nd in $NotDuplicates ) {
        
            # Match the first part of $pd to $nd
            If ( [regex]::Match($pd.BaseName,'^(.*)(\s\(\d*\))$').Groups[1].Value -eq $nd.BaseName ) {
            
                # Check for equal file size
                If ( $(Get-Item -Path $pd.FullName).Length -eq $(Get-Item -Path $nd.FullName).Length ) {
                
                    # Make sure the file still exists before writing any log messages
                    $ToDelete = $pd.FullName
                    If ( Test-Path $ToDelete ) {
                    
                        # Delete the duplicate file
                        LogMsg "Deleting duplicate download: ""${ToDelete}"""
                        Try { Remove-Item -Path $ToDelete -Force -ErrorAction SilentlyContinue }
                        Catch { LogErr $_.Exception.Message }
                    }
                }
            }
        }
    }

    # Remove old Outlook backup files
    $OldOutlookBackupFiles = Get-ChildItem -Path "${userProfile}\AppData\Local\Microsoft\Outlook\*" -File -Filter '*.bak' -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt ((Get-Date) - $TimeDelta) }
    If ( $OldOutlookBackupFiles ) {
        LogMsg "Found Outlook backup files older than ${OlderThan} days:"
        ForEach ( $file in $OldOutlookBackupFiles ) {
            $path = $file.FullName
            LogMsg "Deleting: ""${path}"""
            Try { Remove-Item -Path $path -Force -ErrorAction SilentlyContinue }
            Catch { LogErr $_.Exception.Message }
        }
    }
}

# Silently run cleanmgr.exe with default settings
# TODO: This does not run silently - commenting out for now!
#Try {
#    LogMsg "Running cleanmgr.exe with default settings for very low disk space"
#    Start-Process "cleanmgr.exe" -ArgumentList "/VERYLOWDISK"
#    LogMsg "  - Finished"
#}
#Catch { LogErr $_.Exception.Message }