# Get-RecentDocs.ps1 # Lists recently opened documents from OpenSavePidlMRU registry key param( [int]$MaxPerType = 10, [switch]$ShowAll ) Write-Host "=== Recently Opened Documents ===" -ForegroundColor Cyan Write-Host "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU" if ($ShowAll) { $MaxPerType = [int]::MaxValue Write-Host "Showing all entries`n" -ForegroundColor Yellow } else { Write-Host "Showing top $MaxPerType per type (use -ShowAll or -MaxPerType N to see more)`n" -ForegroundColor Yellow } function Convert-PidlMRU { param([byte[]]$data) if (-not $data -or $data.Length -lt 10) { return "" } try { # Convert to Unicode string $unicodeText = [System.Text.Encoding]::Unicode.GetString($data) # Remove null characters $cleaned = $unicodeText -replace '\x00', '' # Try to extract valid file path (Windows path pattern) if ($cleaned -match '([A-Z]:\\(?:[^<>:"|?*\x00-\x1F]+\\)*[^<>:"|?*\x00-\x1F\\]+)') { return $matches[1] } # Extract filename - match only valid filename characters # This regex looks for a sequence that starts with alphanumeric and includes a file extension if ($cleaned -match '([a-zA-Z0-9][a-zA-Z0-9._\- ]{0,200}\.[a-zA-Z0-9]{1,10})') { return $matches[1] } # Fallback: filter to printable ASCII only and look for pattern $printable = -join ($cleaned.ToCharArray() | Where-Object { ($_ -ge 32 -and $_ -le 126) }) # Try again with printable string if ($printable -match '([a-zA-Z0-9][a-zA-Z0-9._\- ]{0,200}\.[a-zA-Z0-9]{1,10})') { return $matches[1] } return "" } catch { return "" } } try { $mruPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU" if (Test-Path $mruPath) { # Get all extension subkeys $subKeys = Get-ChildItem -Path $mruPath -ErrorAction SilentlyContinue | Sort-Object PSChildName if ($subKeys) { $totalFiles = 0 $totalStored = 0 foreach ($subKey in $subKeys) { $extension = $subKey.PSChildName $props = Get-ItemProperty -Path $subKey.PSPath -ErrorAction SilentlyContinue # Get MRUListEx for ordering if ($props.MRUListEx) { $files = @() for ($i = 0; $i -lt $props.MRUListEx.Length - 4; $i += 4) { $index = [BitConverter]::ToInt32($props.MRUListEx, $i) if ($index -eq -1) { break } $propName = "$index" if ($props.$propName) { $fileName = Convert-PidlMRU -data $props.$propName if ($fileName) { $files += $fileName } } } $totalStored += $files.Count # Only show if we found files if ($files.Count -gt 0) { if ($extension -eq "*") { Write-Host "`n--- All File Types ($($files.Count) total) ---" -ForegroundColor Yellow } else { Write-Host "`n--- .$extension Files ($($files.Count) total) ---" -ForegroundColor Yellow } $count = 0 $displayFiles = $files | Select-Object -First $MaxPerType foreach ($file in $displayFiles) { $count++ $totalFiles++ Write-Host " $count. $file" -ForegroundColor Green } if ($files.Count -gt $MaxPerType) { $remaining = $files.Count - $MaxPerType Write-Host " ... and $remaining more" -ForegroundColor Gray } } } } Write-Host "`n=== Summary ===" -ForegroundColor Cyan Write-Host "Total stored: $totalStored files" -ForegroundColor Green Write-Host "Displayed: $totalFiles files" -ForegroundColor Green if ($totalFiles -eq 0) { Write-Host "`nNo readable file paths found in MRU data" -ForegroundColor Gray Write-Host "The PIDL binary format may require more advanced parsing" -ForegroundColor Gray } } else { Write-Host "`nNo recent file history found" -ForegroundColor Gray } } else { Write-Host "`nOpenSavePidlMRU registry key not found" -ForegroundColor Gray } } catch { Write-Host "Error: $_" -ForegroundColor Red } Write-Host "`nNote: PIDL data parsing is limited. For complete analysis, use forensic tools like Registry Explorer" -ForegroundColor Cyan