122 lines
4.3 KiB
PowerShell
122 lines
4.3 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Specifies a directory and lists all processes that have open file handles within that directory and its
|
|
subdirectories.
|
|
|
|
.DESCRIPTION
|
|
This script utilizes the handle.exe tool from Microsoft's Sysinternals suite to find open file handles.
|
|
It filters the results to show only file handles within the specified target directory path.
|
|
The script requires handle.exe to be downloaded and its path correctly configured in the $handleExePath
|
|
variable.
|
|
For best results, run this script with Administrator privileges.
|
|
|
|
.PARAMETER TargetDirectory
|
|
The path to the directory to scan for open file handles. Defaults to the Windows directory (C:\Windows).
|
|
|
|
.EXAMPLE
|
|
.\Find-FileHandles.ps1
|
|
(Scans the default C:\Windows directory)
|
|
|
|
.EXAMPLE
|
|
.\Find-FileHandles.ps1 -TargetDirectory "D:\Project\video-av1"
|
|
(Scans the D:\Project\video-av1 directory)
|
|
#>
|
|
param (
|
|
[string]$TargetDirectory = $env:SystemRoot # Defaults to C:\Windows
|
|
)
|
|
|
|
# 콘솔 인코딩 설정 (한글 깨짐 방지)
|
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
|
|
|
# --- CONFIGURATION ---
|
|
# handle.exe 경로 자동 탐지
|
|
$possiblePaths = @(
|
|
"C:\Sysinternals\handle.exe",
|
|
"$env:ProgramFiles\Sysinternals\handle.exe",
|
|
"$env:USERPROFILE\Downloads\handle.exe",
|
|
"$env:TEMP\handle.exe",
|
|
"handle.exe" # PATH에 있는 경우
|
|
)
|
|
|
|
$handleExePath = $null
|
|
foreach ($path in $possiblePaths) {
|
|
if (Test-Path $path) {
|
|
$handleExePath = $path
|
|
break
|
|
}
|
|
}
|
|
|
|
# PATH에서 handle.exe 찾기
|
|
if (-not $handleExePath) {
|
|
try {
|
|
$handleExePath = (Get-Command "handle.exe" -ErrorAction Stop).Source
|
|
} catch {
|
|
$handleExePath = $null
|
|
}
|
|
}
|
|
# ---------------------
|
|
|
|
# handle.exe 파일 존재 여부 확인
|
|
if (-not $handleExePath -or -not (Test-Path $handleExePath)) {
|
|
Write-Host "[ERROR] handle.exe not found in any of the following locations:" -ForegroundColor Red
|
|
$possiblePaths | ForEach-Object { Write-Host " - $_" -ForegroundColor Yellow }
|
|
Write-Host ""
|
|
Write-Host "Please download handle.exe from:" -ForegroundColor Cyan
|
|
Write-Host "https://learn.microsoft.com/en-us/sysinternals/downloads/handle" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
Write-Host "And place it in one of the above locations, or add it to your PATH." -ForegroundColor Green
|
|
return
|
|
}
|
|
|
|
Write-Host "Scanning for open file handles in '$TargetDirectory'..."
|
|
Write-Host "This may take a moment..."
|
|
|
|
# Execute handle.exe to get all open file handle information
|
|
try {
|
|
Write-Host "Executing handle.exe..." -ForegroundColor Gray
|
|
$handleOutput = & $handleExePath -nobanner -a -u "$TargetDirectory" 2>$null | Out-String
|
|
}
|
|
catch {
|
|
Write-Host "[ERROR] Failed to execute handle.exe: $($_.Exception.Message)" -ForegroundColor Red
|
|
return
|
|
}
|
|
|
|
# 결과를 저장할 배열 초기화
|
|
$foundProcesses = @()
|
|
|
|
# Analyze handle.exe output line by line
|
|
if ($handleOutput) {
|
|
# Use regex to extract process name, PID, and file path
|
|
# handle.exe output format variations:
|
|
# "ProcessName.exe pid: 1234 type: File C:\path\to\file"
|
|
# "ProcessName.exe pid: 1234 user: DOMAIN\User type: File C:\path\to\file"
|
|
$regex = "^(.+?)\s+pid:\s*(\d+)\s+.*?\s+type:\s+File\s+(.+?)\s*$"
|
|
|
|
$handleOutput.Split([Environment]::NewLine) | ForEach-Object {
|
|
if ($_ -match $regex) {
|
|
$processName = $matches[1].Trim()
|
|
$processId = [int]$matches[2]
|
|
$filePath = $matches[3].Trim()
|
|
|
|
# 지정된 디렉토리 경로에 포함되는 결과만 필터링
|
|
if ($filePath.StartsWith($TargetDirectory, [System.StringComparison]::OrdinalIgnoreCase)) {
|
|
# PSCustomObject를 생성
|
|
$customObject = [PSCustomObject]@{
|
|
ProcessName = $processName
|
|
PID = $processId
|
|
FilePath = $filePath
|
|
}
|
|
$foundProcesses += $customObject
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# 결과 출력
|
|
if ($foundProcesses.Count -gt 0) {
|
|
Write-Host "`n[+] Found $($foundProcesses.Count) open file handles in '$TargetDirectory':"
|
|
$foundProcesses | Sort-Object -Property ProcessName, FilePath | Format-Table -AutoSize
|
|
} else {
|
|
Write-Host "`n[-] No open file handles were found for the specified directory."
|
|
} |