Files
video-v1/Find-FileHandles.ps1
2025-10-05 03:42:51 +09:00

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."
}