Merhabalar
KOD İÇERİĞİ ( Koplayama/Taşıma v2.2 PS1 Betiği )
KOD İÇERİĞİ ( Yüksek Güvenlikli Silme v1.1 PS Betiği)
Düzeltilmiş Silme Betiği (v1.2) - Kaynak Konum Eklendi
AÇIKLAMA :
Kopyalama/Taşıma Betiği (v2.2) Özellikleri
1.Yönetici yetkisi kontrolü ve otomatik yükseltme
2.GUI tabanlı kaynak ve hedef konum seçimi (Windows diyalog pencereleri)
3.Klasör veya dosya seçimi desteği
4.Tekli veya çoklu dosya seçimi
5.Kopyalama veya taşıma işlemi seçimi
6.Gerçek zamanlı hız göstergesi (MB/sn cinsinden)
7.İlerleme çubuğu ile dosya bazlı takip
8.SHA-256 hash hesaplama ile bütünlük doğrulama
9.Kritik sistem yolları koruması (Windows, System32, Program Files vb.)
10.Sürücü kök dizinleri koruması (C:, D:\ vb.)
11.Klasör seçildiğinde klasörün kendisi de dahil kopyalama/taşıma
12.Taşıma sonrası boş kalan dizinlerin otomatik temizliği
13.Hata durumunda işlemi güvenli şekilde durdurma
14.Detaylı HTML rapor oluşturma
15.Base64 kodlanmış HTML yedek raporu (HTML64)
16.Hata durumunda detaylı TXT hata raporu
Güvenli Silme Betiği (v1.2) Özellikleri
1.Yönetici yetkisi kontrolü ve otomatik yükseltme
2.GUI tabanlı silinecek nesne seçimi
3.Klasör veya dosya seçimi desteği
4.Tekli veya çoklu dosya seçimi
5.Geri dönüşüm kutusuna gönderme veya kalıcı silme seçimi
6.Silme öncesi detaylı önizleme penceresi
7.Kalıcı silme için çift onay mekanizması
8.SHA-256 hash hesaplama ile silinen dosyaların kanıtlanması
9.Kritik sistem yolları koruması (Windows, System32, Program Files vb.)
10.Sürücü kök dizinleri koruması (C:, D:\ vb.)
11.Klasör seçildiğinde klasörün kendisi ve içindekilerin silinmesi
12.Boş kalan dizinlerin otomatik temizliği
13.Geri dönüşüm kutusu desteği (yanlışlıkta kurtarma şansı)
14.Hata durumunda diğer dosyalara devam etme (izolasyon)
15.Detaylı HTML rapor oluşturma (kaynak konum bilgisi dahil)
16.Base64 kodlanmış HTML yedek raporu (HTML64)
17.Hata durumunda detaylı TXT hata raporu
18.Kritik hata durumunda işlemi güvenli şekilde durdurma
İki Betiğin Ortak Özellikleri :
1.Windows 10/11 uyumlu
2.Türkçe karakter desteği
3.Hata yönetimi ve raporlama sistemi
4.Masaüstüne otomatik rapor kaydetme
5.Sistem güvenliği öncelikli tasarım
ÖRNEK ÇIKTI EKRAN GÖRÜNTÜSÜ : (Silme)
Güle güle kullanın...
KOD İÇERİĞİ ( Koplayama/Taşıma v2.2 PS1 Betiği )
Kod:
# =====================================================================
# Gelişmiş Kopyalama / Taşıma Betiği v2.2
# xcopy /o/x/e/h/k mantığı — Güvenli, GUI'li, Raporlu
# =====================================================================
# ── 1. YÖNETİCİ YETKİSİ KONTROLÜ ─────────────────────────────────────
$principal = New-Object Security.Principal.WindowsPrincipal(
[Security.Principal.WindowsIdentity]::GetCurrent()
)
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Host "[BİLGİ] Yönetici yetkisi algılanmadı. Betik yeniden başlatılıyor..." -ForegroundColor Yellow
Start-Process powershell.exe -Verb RunAs -ArgumentList `
"-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$($MyInvocation.MyCommand.Path)`""
exit
}
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[System.Windows.Forms.Application]::EnableVisualStyles()
$desktop = [Environment]::GetFolderPath("Desktop")
# ── KRİTİK SİSTEM YOLU DENETLEYİCİSİ ─────────────────────────────────
function Test-IsCriticalPath {
param([string]$Path)
$criticalDirs = @(
$env:SystemRoot
(Join-Path $env:SystemRoot "System32")
(Join-Path $env:SystemRoot "SysWOW64")
(Join-Path $env:SystemRoot "WinSxS")
(Join-Path $env:SystemRoot "SystemApps")
$env:ProgramFiles
${env:ProgramFiles(x86)}
$env:ProgramData
(Join-Path $env:SystemDrive "Users\Default")
(Join-Path $env:SystemDrive "Users\All Users")
(Join-Path $env:SystemDrive "`$Recycle.Bin")
(Join-Path $env:SystemDrive "System Volume Information")
(Join-Path $env:SystemDrive "Recovery")
(Join-Path $env:SystemDrive "Boot")
(Join-Path $env:SystemDrive "EFI")
(Join-Path $env:SystemDrive "PerfLogs")
(Join-Path $env:SystemDrive "MSOCache")
(Join-Path $env:SystemDrive "Config.Msi")
(Join-Path $env:SystemDrive "`$WinREAgent")
(Join-Path $env:SystemDrive "Windows.old")
) | Where-Object { $_ -and (Test-Path $_ -ErrorAction SilentlyContinue) }
$criticalFiles = @(
"pagefile.sys","hiberfil.sys","swapfile.sys",
"bootmgr","BOOTNXT","ntldr","ntdetect.com"
)
try {
$norm = [System.IO.Path]::GetFullPath($Path).TrimEnd('\','/')
} catch {
return $false
}
if ($norm -match '^[A-Za-z]:$') { return $true }
foreach ($cd in $criticalDirs) {
try {
$normCD = [System.IO.Path]::GetFullPath($cd).TrimEnd('\','/')
if ($norm -eq $normCD -or
$norm.StartsWith("$normCD\", [StringComparison]::OrdinalIgnoreCase)) {
return $true
}
} catch { continue }
}
if ($criticalFiles -contains [System.IO.Path]::GetFileName($Path)) { return $true }
return $false
}
function Assert-SafePath {
param([string]$Path, [string]$Label)
if (Test-IsCriticalPath $Path) {
[System.Windows.Forms.MessageBox]::Show(
"GÜVENLİK UYARISI`n`n" +
"'$Label' olarak seçilen yol kritik bir sistem konumudur:`n$Path`n`n" +
"Windows'un bütünlüğünü korumak amacıyla bu işlem engellenmiştir.",
"Kritik Yol Engellendi", "OK", "Warning"
)
return $false
}
return $true
}
# =====================================================================
# ANA İŞLEM — try/catch ile tam koruma
# =====================================================================
try {
# ── 2. KULLANICI SEÇİMLERİ (GUI) ─────────────────────────────────
# 2a) Nesne türü: Klasör mü Dosya mı?
$typeResult = [System.Windows.Forms.MessageBox]::Show(
"Lütfen kopyalanacak/taşınacak nesne türünü seçin:`n`n" +
" [ Evet ] -> KLASÖR (Dizin)`n" +
" [ Hayır ] -> DOSYA",
"Nesne Türü Seçimi", "YesNo", "Question"
)
if ($typeResult -eq "No") { $isFolder = $false }
elseif ($typeResult -eq "Yes") { $isFolder = $true }
else { exit }
# 2b) Kopyala mı Taşı mı?
$actResult = [System.Windows.Forms.MessageBox]::Show(
"İşlem türünü seçin:`n`n" +
" [ Evet ] -> KOPYALA`n" +
" [ Hayır ] -> TAŞI",
"İşlem Türü", "YesNo", "Question"
)
$isMove = ($actResult -eq "No")
# 2c) Tekli mi Çoklu mu?
$isMulti = $false
if (-not $isFolder) {
$multiResult = [System.Windows.Forms.MessageBox]::Show(
"Birden fazla dosya seçmek istiyor musunuz?`n`n" +
" [ Evet ] -> Çoklu dosya seçimi`n" +
" [ Hayır ] -> Tek dosya seçimi",
"Çoklu Seçim", "YesNo", "Question"
)
$isMulti = ($multiResult -eq "Yes")
}
# ── 3. KAYNAK KONUM SEÇİCİ ───────────────────────────────────────
$sourcePaths = @()
if ($isFolder) {
$dlg = New-Object System.Windows.Forms.FolderBrowserDialog
$dlg.Description = "KAYNAK KLASÖR seçin:`n(Seçilen klasörün KENDİSİ de kopyalanacak/taşınacaktır)"
$dlg.ShowNewFolderButton = $false
if ($dlg.ShowDialog() -ne "OK") { exit }
$sourcePaths += $dlg.SelectedPath
}
else {
$dlg = New-Object System.Windows.Forms.OpenFileDialog
$dlg.Title = if ($isMulti) {
"KAYNAK DOSYALARI seçin (Ctrl / Shift ile çoklu)"
} else {
"KAYNAK DOSYA seçin"
}
$dlg.Multiselect = $isMulti
$dlg.Filter = "Tüm Dosyalar (*.*)|*.*"
if ($dlg.ShowDialog() -ne "OK") { exit }
$sourcePaths = $dlg.FileNames
}
# Kaynak yol güvenlik denetimi
foreach ($sp in $sourcePaths) {
if (-not (Assert-SafePath $sp "KAYNAK")) { exit }
}
# ── 4. HEDEF KONUM SEÇİCİ ────────────────────────────────────────
$destDlg = New-Object System.Windows.Forms.FolderBrowserDialog
$destDlg.Description = "HEDEF KONUM seçin:"
$destDlg.ShowNewFolderButton = $true
if ($destDlg.ShowDialog() -ne "OK") { exit }
$destPath = $destDlg.SelectedPath
if (-not (Assert-SafePath $destPath "HEDEF")) { exit }
# ── 5. DOSYA LİSTESİNİ OLUŞTUR ───────────────────────────────────
$allFiles = @()
$baseSourcePath = ""
if ($isFolder) {
$baseSourcePath = Split-Path $sourcePaths[0] -Parent
$allFiles = @(Get-ChildItem -LiteralPath $sourcePaths[0] `
-Recurse -File -Force -ErrorAction Stop)
}
else {
$baseSourcePath = Split-Path $sourcePaths[0] -Parent
foreach ($p in $sourcePaths) {
$allFiles += Get-Item -LiteralPath $p -Force -ErrorAction Stop
}
}
if ($allFiles.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show(
"Seçilen konumda dosya bulunamadı.", "Boş Konum", "OK", "Information"
)
exit
}
$totalBytes = ($allFiles | Measure-Object -Property Length -Sum).Sum
$totalMB = [math]::Round($totalBytes / 1MB, 2)
# ── 6. HASH HESAPLAMA ────────────────────────────────────────────
Write-Host "Dosya bütünlük hash'leri hesaplanıyor (SHA-256)..." -ForegroundColor Cyan
$hashTable = @{}
$processedSize = 0
foreach ($f in $allFiles) {
$h = (Get-FileHash -LiteralPath $f.FullName -Algorithm SHA256 -ErrorAction Stop).Hash
$hashTable[$f.FullName] = $h
$processedSize += $f.Length
[int]$pct = [math]::Min(100, [math]::Round(($processedSize / [math]::Max($totalBytes,1)) * 100))
Write-Progress -Activity "Hash Hesaplanıyor" -Status $f.Name -PercentComplete $pct
}
Write-Progress -Activity "Hash Hesaplanıyor" -Completed
$concatHashes = ($hashTable.Values | Sort-Object) -join ""
$sha = [System.Security.Cryptography.SHA256]::Create()
$combinedBytes = $sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($concatHashes))
$finalHash = [BitConverter]::ToString($combinedBytes).Replace("-", "")
# ── 7. KOPYALAMA / TAŞIMA ────────────────────────────────────────
$verb = if ($isMove) { "Taşınıyor" } else { "Kopyalanıyor" }
Write-Host "$verb ... ($($allFiles.Count) dosya, $totalMB MB)" -ForegroundColor Green
$copiedBytes = 0
$startTime = Get-Date
$errorDetails = [System.Collections.ArrayList]::new()
$successCount = 0
foreach ($f in $allFiles) {
$relPath = $f.FullName.Substring($baseSourcePath.Length)
$destFile = Join-Path $destPath $relPath
$destDir = Split-Path $destFile -Parent
if (-not (Test-Path -LiteralPath $destDir)) {
New-Item -ItemType Directory -Path $destDir -Force -ErrorAction Stop | Out-Null
}
$fileStart = Get-Date
try {
if ($isMove) {
Move-Item -LiteralPath $f.FullName -Destination $destFile -ErrorAction Stop
} else {
Copy-Item -LiteralPath $f.FullName -Destination $destFile -ErrorAction Stop
}
}
catch {
$errorDetails.Add(
"DOSYA : $($f.FullName)`n" +
"HATA : $($_.Exception.Message)`n" +
"ZAMAN : $(Get-Date -Format 'HH:mm:ss')`n"
) | Out-Null
continue
}
$fileEnd = Get-Date
$dur = [math]::Max(($fileEnd - $fileStart).TotalSeconds, 0.01)
$speedMBs = [math]::Round(($f.Length / 1MB) / $dur, 2)
$copiedBytes += $f.Length
$successCount++
[int]$pct = [math]::Min(100, [math]::Round(($copiedBytes / [math]::Max($totalBytes,1)) * 100))
Write-Progress -Activity "$verb ($speedMBs MB/sn)" `
-Status "$($successCount)/$($allFiles.Count) $($f.Name)" `
-PercentComplete $pct
}
$endTime = Get-Date
$totalSeconds = [math]::Max(($endTime - $startTime).TotalSeconds, 0.01)
$avgSpeed = [math]::Round(($copiedBytes / 1MB) / $totalSeconds, 2)
Write-Progress -Activity $verb -Completed
# ── Taşıma sonrası boş dizin temizliği ───────────────────────────
if ($isMove -and $isFolder -and $errorDetails.Count -eq 0) {
$emptyDirs = Get-ChildItem -LiteralPath $sourcePaths[0] -Recurse -Directory -Force |
Sort-Object { $_.FullName.Length } -Descending |
Where-Object { (Get-ChildItem -LiteralPath $_.FullName -Force).Count -eq 0 }
foreach ($d in $emptyDirs) {
Remove-Item -LiteralPath $d.FullName -Force -ErrorAction SilentlyContinue
}
if ((Get-ChildItem -LiteralPath $sourcePaths[0] -Force -ErrorAction SilentlyContinue).Count -eq 0) {
Remove-Item -LiteralPath $sourcePaths[0] -Force -ErrorAction SilentlyContinue
}
}
# ── 8. HATA RAPORU ───────────────────────────────────────────────
if ($errorDetails.Count -gt 0) {
$errText = @"
================================================================
HATA RAPORU — $(Get-Date -Format "dd.MM.yyyy HH:mm:ss")
================================================================
İşlem sırasında $($errorDetails.Count) dosyada hata oluştu.
Sisteminize ve diğer dosyalarınıza ZARAR GELMEMİŞTİR.
Başarılı işlem: $successCount / $($allFiles.Count)
$($errorDetails -join "`n")
================================================================
"@
$errPath = Join-Path $desktop "Hata_Raporu_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
Set-Content -LiteralPath $errPath -Value $errText -Encoding UTF8
}
# ── 9. HTML RAPORU ───────────────────────────────────────────────
$actionLabel = if ($isMove) { "Taşıma" } else { "Kopyalama" }
$statusColor = if ($errorDetails.Count -eq 0) { "#27ae60" } else { "#e74c3c" }
$statusText = if ($errorDetails.Count -eq 0) { "BAŞARILI" } else { "KISMİ BAŞARI ($($errorDetails.Count) hata)" }
$hashRows = ""
$displayFiles = $allFiles | Select-Object -First 50
foreach ($f in $displayFiles) {
$hashRows += "<tr><td>$($f.Name)</td><td style='font-family:monospace;font-size:0.8em;'>$($hashTable[$f.FullName])</td></tr>`n"
}
if ($allFiles.Count -gt 50) {
$hashRows += "<tr><td colspan='2' style='text-align:center;color:#888;'>... ve $($allFiles.Count - 50) dosya daha</td></tr>"
}
$html = @"
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<title>İşlem Raporu</title>
<style>
*{box-sizing:border-box}
body{font-family:'Segoe UI',Tahoma,sans-serif;background:#f0f2f5;margin:0;padding:30px}
.card{max-width:860px;margin:auto;background:#fff;border-radius:10px;
box-shadow:0 6px 20px rgba(0,0,0,.08);overflow:hidden}
.header{background:linear-gradient(135deg,#2c3e50,#3498db);color:#fff;padding:28px 32px}
.header h1{margin:0;font-size:1.5em}
.header .badge{display:inline-block;margin-top:8px;padding:4px 14px;
border-radius:20px;font-weight:700;font-size:.9em;background:$statusColor}
.body{padding:28px 32px}
table{width:100%;border-collapse:collapse;margin:18px 0}
th,td{padding:10px 14px;border:1px solid #e0e0e0;text-align:left}
th{background:#3498db;color:#fff}
tr:nth-child(even){background:#f9fbfd}
.mono{font-family:Consolas,'Courier New',monospace;font-size:.85em;word-break:break-all}
.hash-box{background:#ecf0f1;padding:14px;border-radius:6px;margin:10px 0}
.footer{text-align:center;color:#aaa;font-size:.8em;padding:16px}
</style>
</head>
<body>
<div class="card">
<div class="header">
<h1>$actionLabel İşlem Raporu</h1>
<span class="badge">$statusText</span>
</div>
<div class="body">
<table>
<tr><th>Metrik</th><th>Değer</th></tr>
<tr><td>Tarih / Saat</td><td>$(Get-Date -Format "dd.MM.yyyy HH:mm:ss")</td></tr>
<tr><td>İşlem Türü</td><td><strong>$actionLabel</strong></td></tr>
<tr><td>Kaynak</td><td>$baseSourcePath</td></tr>
<tr><td>Hedef</td><td>$destPath</td></tr>
<tr><td>Dosya Sayısı</td><td>$($allFiles.Count)</td></tr>
<tr><td>Toplam Boyut</td><td>$totalMB MB ($totalBytes bayt)</td></tr>
<tr><td>Geçen Süre</td><td>$([math]::Round($totalSeconds,2)) saniye</td></tr>
<tr><td>Ortalama Hız</td><td><strong>$avgSpeed MB/sn</strong></td></tr>
<tr><td>Başarılı</td><td>$successCount / $($allFiles.Count)</td></tr>
</table>
<h3>Bütünlük Doğrulama (SHA-256)</h3>
<div class="hash-box mono">$finalHash</div>
<h3>Dosya Hash Detayları</h3>
<table>
<tr><th>Dosya Adı</th><th>SHA-256</th></tr>
$hashRows
</table>
</div>
<div class="footer">Gelişmiş Kopyalama Betiği v2.2 — $(Get-Date -Format "yyyy")</div>
</div>
</body>
</html>
"@
$htmlPath = Join-Path $desktop "Islem_Raporu_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
Set-Content -LiteralPath $htmlPath -Value $html -Encoding UTF8
$b64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($html))
$b64Path = Join-Path $desktop "Islem_Raporu_HTML64_$(Get-Date -Format 'yyyyMMdd_HHmmss').b64"
Set-Content -LiteralPath $b64Path -Value $b64 -Encoding UTF8
# ── BİTİŞ BİLDİRİMİ ──────────────────────────────────────────────
$summary = "İşlem tamamlandı!`n`n" +
"Başarılı: $successCount / $($allFiles.Count)`n" +
"Ortalama Hız: $avgSpeed MB/sn`n" +
"Toplam Boyut: $totalMB MB`n`n" +
"Raporlar masaüstüne kaydedildi."
if ($errorDetails.Count -gt 0) {
$summary += "`n`nUyarı: $($errorDetails.Count) hata oluştu — Hata_Raporu.txt'ye bakın."
}
[System.Windows.Forms.MessageBox]::Show($summary, "İşlem Tamamlandı", "OK", "Information")
}
catch {
$errReport = @"
================================================================
KRİTİK HATA RAPORU — $(Get-Date -Format "dd.MM.yyyy HH:mm:ss")
================================================================
İşlem güvenlik nedeniyle DURDURULMUŞTUR.
Sisteminize ve dosyalarınıza zarar gelmemiştir.
HATA MESAJI :
$($_.Exception.Message)
HATA KONUMU :
$($_.InvocationInfo.PositionMessage)
YIĞIN İZİ :
$($_.ScriptStackTrace)
================================================================
"@
$critPath = Join-Path $desktop "Kritik_Hata_Raporu_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
Set-Content -LiteralPath $critPath -Value $errReport -Encoding UTF8
[System.Windows.Forms.MessageBox]::Show(
"Kritik bir hata oluştu ve işlem GÜVENLİ ŞEKİLDE durduruldu.`n`n" +
"Detay: $critPath",
"Kritik Hata", "OK", "Error"
)
}
KOD İÇERİĞİ ( Yüksek Güvenlikli Silme v1.1 PS Betiği)
Düzeltilmiş Silme Betiği (v1.2) - Kaynak Konum Eklendi
Kod:
# =====================================================================
# Güvenli Silme Betiği v1.2
# Çift onaylı, geri dönüşüm destekli, raporlu, kritik-korumalı
# =====================================================================
# ── 1. YÖNETİCİ YETKİSİ KONTROLÜ ─────────────────────────────────────
$principal = New-Object Security.Principal.WindowsPrincipal(
[Security.Principal.WindowsIdentity]::GetCurrent()
)
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Host "[BİLGİ] Yönetici yetkisi gerekli. Betik yeniden başlatılıyor..." -ForegroundColor Yellow
Start-Process powershell.exe -Verb RunAs -ArgumentList `
"-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$($MyInvocation.MyCommand.Path)`""
exit
}
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName Microsoft.VisualBasic
[System.Windows.Forms.Application]::EnableVisualStyles()
$desktop = [Environment]::GetFolderPath("Desktop")
# ── KRİTİK SİSTEM YOLU DENETLEYİCİSİ ─────────────────────────────────
function Test-IsCriticalPath {
param([string]$Path)
$criticalDirs = @(
$env:SystemRoot
(Join-Path $env:SystemRoot "System32")
(Join-Path $env:SystemRoot "SysWOW64")
(Join-Path $env:SystemRoot "WinSxS")
(Join-Path $env:SystemRoot "SystemApps")
$env:ProgramFiles
${env:ProgramFiles(x86)}
$env:ProgramData
(Join-Path $env:SystemDrive "Users\Default")
(Join-Path $env:SystemDrive "Users\All Users")
(Join-Path $env:SystemDrive "Users\Public")
(Join-Path $env:SystemDrive "`$Recycle.Bin")
(Join-Path $env:SystemDrive "System Volume Information")
(Join-Path $env:SystemDrive "Recovery")
(Join-Path $env:SystemDrive "Boot")
(Join-Path $env:SystemDrive "EFI")
(Join-Path $env:SystemDrive "PerfLogs")
(Join-Path $env:SystemDrive "MSOCache")
(Join-Path $env:SystemDrive "Config.Msi")
(Join-Path $env:SystemDrive "`$WinREAgent")
(Join-Path $env:SystemDrive "Windows.old")
(Join-Path $env:SystemDrive "Program Files")
(Join-Path $env:SystemDrive "Program Files (x86)")
) | Where-Object { $_ -and (Test-Path $_ -ErrorAction SilentlyContinue) }
$criticalFiles = @(
"pagefile.sys","hiberfil.sys","swapfile.sys",
"bootmgr","BOOTNXT","ntldr","ntdetect.com",
"autoexec.bat","config.sys","io.sys","msdos.sys"
)
try {
$norm = [System.IO.Path]::GetFullPath($Path).TrimEnd('\','/')
} catch { return $false }
if ($norm -match '^[A-Za-z]:$') { return $true }
foreach ($cd in $criticalDirs) {
try {
$normCD = [System.IO.Path]::GetFullPath($cd).TrimEnd('\','/')
if ($norm -eq $normCD -or
$norm.StartsWith("$normCD\", [StringComparison]::OrdinalIgnoreCase)) {
return $true
}
} catch { continue }
}
if ($criticalFiles -contains [System.IO.Path]::GetFileName($Path)) { return $true }
return $false
}
function Assert-SafePath {
param([string]$Path, [string]$Label)
if (Test-IsCriticalPath $Path) {
[System.Windows.Forms.MessageBox]::Show(
"GÜVENLİK UYARISI`n`n" +
"'$Label' olarak seçilen yol KRİTİK bir sistem konumudur:`n`n$Path`n`n" +
"Windows'un bütünlüğünü korumak amacıyla bu işlem ENGELLENDİ.`n" +
"Sisteminize zarar gelmesi önlenmiştir.",
"Kritik Yol Engellendi", "OK", "Stop"
)
return $false
}
return $true
}
# =====================================================================
# ANA İŞLEM
# =====================================================================
try {
# ── 2. NESNE TÜRÜ SEÇİMİ ────────────────────────────────────────
$typeResult = [System.Windows.Forms.MessageBox]::Show(
"Silinecek nesne türünü seçin:`n`n" +
" [ Evet ] -> KLASÖR (Dizin)`n" +
" [ Hayır ] -> DOSYA",
"Nesne Türü Seçimi", "YesNo", "Question"
)
if ($typeResult -eq "No") { $isFolder = $false }
elseif ($typeResult -eq "Yes") { $isFolder = $true }
else { exit }
# ── 3. SİLME MODU SEÇİMİ ────────────────────────────────────────
$modeResult = [System.Windows.Forms.MessageBox]::Show(
"SİLME YÖNTEMİ seçin:`n`n" +
" [ Evet ] -> Geri Dönüşüm Kutusu'na gönder`n" +
" (Güvenli — isterseniz geri getirebilirsiniz)`n`n" +
" [ Hayır ] -> KALICI OLARAK SİL`n" +
" (DİKKAT: Geri getirilemez!)",
"Silme Yöntemi", "YesNo", "Warning"
)
if ($modeResult -eq "Yes") {
$useRecycleBin = $true
$modeLabel = "Geri Dönüşüm Kutusu"
} else {
$useRecycleBin = $false
$modeLabel = "Kalıcı Silme"
}
# ── 4. ÇOKLU SEÇİM SORUSU ───────────────────────────────────────
$isMulti = $false
if (-not $isFolder) {
$multiResult = [System.Windows.Forms.MessageBox]::Show(
"Birden fazla dosya seçmek istiyor musunuz?",
"Çoklu Seçim", "YesNo", "Question"
)
$isMulti = ($multiResult -eq "Yes")
}
# ── 5. KAYNAK SEÇİMİ ────────────────────────────────────────────
$sourcePaths = @()
if ($isFolder) {
$dlg = New-Object System.Windows.Forms.FolderBrowserDialog
$dlg.Description = "SİLİNECEK KLASÖR seçin:`n(Klasörün KENDİSİ ve içindekiler silinecektir)"
$dlg.ShowNewFolderButton = $false
if ($dlg.ShowDialog() -ne "OK") { exit }
$sourcePaths += $dlg.SelectedPath
}
else {
$dlg = New-Object System.Windows.Forms.OpenFileDialog
$dlg.Title = if ($isMulti) { "SİLİNECEK DOSYALARI seçin (Ctrl/Shift ile çoklu)" } `
else { "SİLİNECEK DOSYA seçin" }
$dlg.Multiselect = $isMulti
$dlg.Filter = "Tüm Dosyalar (*.*)|*.*"
if ($dlg.ShowDialog() -ne "OK") { exit }
$sourcePaths = $dlg.FileNames
}
foreach ($sp in $sourcePaths) {
if (-not (Assert-SafePath $sp "SİLİNECEK KAYNAK")) { exit }
}
# ── 6. DOSYA LİSTESİNİ OLUŞTUR ───────────────────────────────────
$allFiles = @()
$topLevelItems = @()
$sourceLocation = ""
if ($isFolder) {
$sourceLocation = $sourcePaths[0]
$topLevelItems += Get-Item -LiteralPath $sourcePaths[0] -Force -ErrorAction Stop
$allFiles = @(Get-ChildItem -LiteralPath $sourcePaths[0] `
-Recurse -File -Force -ErrorAction Stop)
}
else {
$sourceLocation = Split-Path $sourcePaths[0] -Parent
foreach ($p in $sourcePaths) {
$item = Get-Item -LiteralPath $p -Force -ErrorAction Stop
$topLevelItems += $item
$allFiles += $item
}
}
if ($allFiles.Count -eq 0 -and $topLevelItems.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show(
"Seçilen konum boş veya erişilemiyor.", "Boş Konum", "OK", "Information"
)
exit
}
$totalBytes = 0
foreach ($f in $allFiles) { $totalBytes += $f.Length }
$totalMB = [math]::Round($totalBytes / 1MB, 2)
# ── 7. ÖNİZLEME VE ÇİFT ONAY ─────────────────────────────────────
$previewList = ""
$displayItems = $topLevelItems | Select-Object -First 20
foreach ($it in $displayItems) {
$previewList += " - $($it.FullName)`n"
}
if ($topLevelItems.Count -gt 20) {
$previewList += " ... ve $($topLevelItems.Count - 20) nesne daha`n"
}
$previewMsg = @"
DİKKAT — SİLME İŞLEMİ ÖNİZLEMESİ
Aşağıdaki nesneler $modeLabel yöntemiyle SİLİNECEK:
$previewList
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Kaynak Konum : $sourceLocation
Toplam Dosya Sayısı : $($allFiles.Count)
Toplam Boyut : $totalMB MB ($totalBytes bayt)
Silme Yöntemi : $modeLabel
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
$(if($useRecycleBin){
"Geri dönüşüm kutusuna gönderilecek.`nİsterseniz sonradan geri getirebilirsiniz."
} else {
"KALICI OLARAK SİLİNECEK!`nBu işlem GERİ ALINAMAZ!"
})
Devam etmek istiyor musunuz?
"@
$confirm1 = [System.Windows.Forms.MessageBox]::Show(
$previewMsg, "ÖNİZLEME — 1. Onay", "YesNo", "Warning"
)
if ($confirm1 -ne "Yes") { exit }
if (-not $useRecycleBin) {
$confirm2 = [System.Windows.Forms.MessageBox]::Show(
"SON UYARI`n`n" +
"$($allFiles.Count) dosyayı ($totalMB MB) KALICI OLARAK SİLMEK ÜZERESİNİZ!`n`n" +
"Bu işlem GERİ ALINAMAZ. Emin misiniz?",
"SON ONAY — Geri Alınamaz İşlem", "YesNo", "Stop"
)
if ($confirm2 -ne "Yes") { exit }
}
# ── 8. HASH HESAPLAMA ────────────────────────────────────────────
Write-Host "Silme öncesi dosya hash'leri hesaplanıyor (kanıt için)..." -ForegroundColor Cyan
$hashTable = @{}
$processedSize = 0
foreach ($f in $allFiles) {
try {
$h = (Get-FileHash -LiteralPath $f.FullName -Algorithm SHA256 -ErrorAction Stop).Hash
$hashTable[$f.FullName] = $h
} catch {
$hashTable[$f.FullName] = "HESAPLANAMADI"
}
$processedSize += $f.Length
[int]$pct = [math]::Min(100, [math]::Round(($processedSize / [math]::Max($totalBytes,1)) * 100))
Write-Progress -Activity "Hash Hesaplanıyor (Kanıt)" -Status $f.Name -PercentComplete $pct
}
Write-Progress -Activity "Hash Hesaplanıyor" -Completed
$concatHashes = ($hashTable.Values | Where-Object { $_ -ne "HESAPLANAMADI" } | Sort-Object) -join ""
if ($concatHashes) {
$sha = [System.Security.Cryptography.SHA256]::Create()
$combinedBytes = $sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($concatHashes))
$finalHash = [BitConverter]::ToString($combinedBytes).Replace("-", "")
} else {
$finalHash = "HASH YOK"
}
# ── 9. SİLME İŞLEMİ ──────────────────────────────────────────────
Write-Host "Silme işlemi başlatılıyor..." -ForegroundColor Yellow
$deletedCount = 0
$failedItems = [System.Collections.ArrayList]::new()
$deletedFiles = [System.Collections.ArrayList]::new()
$startTime = Get-Date
foreach ($f in $allFiles) {
try {
if ($useRecycleBin) {
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile(
$f.FullName,
[Microsoft.VisualBasic.FileIO.UIOption]::OnlyErrorDialogs,
[Microsoft.VisualBasic.FileIO.RecycleOption]::SendToRecycleBin
)
} else {
Remove-Item -LiteralPath $f.FullName -Force -ErrorAction Stop
}
$deletedFiles.Add($f) | Out-Null
$deletedCount++
}
catch {
$failedItems.Add([PSCustomObject]@{
Path = $f.FullName
Error = $_.Exception.Message
}) | Out-Null
}
[int]$pct = [math]::Min(100, [math]::Round(($deletedCount / [math]::Max($allFiles.Count,1)) * 100))
Write-Progress -Activity "Siliniyor..." -Status "$deletedCount / $($allFiles.Count)" -PercentComplete $pct
}
if ($isFolder) {
$emptyDirs = Get-ChildItem -LiteralPath $sourcePaths[0] -Recurse -Directory -Force -ErrorAction SilentlyContinue |
Sort-Object { $_.FullName.Length } -Descending |
Where-Object {
try { (Get-ChildItem -LiteralPath $_.FullName -Force -ErrorAction Stop).Count -eq 0 }
catch { $false }
}
foreach ($d in $emptyDirs) {
try {
if ($useRecycleBin) {
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteDirectory(
$d.FullName,
[Microsoft.VisualBasic.FileIO.UIOption]::OnlyErrorDialogs,
[Microsoft.VisualBasic.FileIO.RecycleOption]::SendToRecycleBin
)
} else {
Remove-Item -LiteralPath $d.FullName -Force -ErrorAction Stop
}
} catch { }
}
try {
if ((Get-ChildItem -LiteralPath $sourcePaths[0] -Force -ErrorAction Stop).Count -eq 0) {
if ($useRecycleBin) {
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteDirectory(
$sourcePaths[0],
[Microsoft.VisualBasic.FileIO.UIOption]::OnlyErrorDialogs,
[Microsoft.VisualBasic.FileIO.RecycleOption]::SendToRecycleBin
)
} else {
Remove-Item -LiteralPath $sourcePaths[0] -Force -ErrorAction Stop
}
}
} catch { }
}
$endTime = Get-Date
$totalSeconds = [math]::Max(($endTime - $startTime).TotalSeconds, 0.01)
Write-Progress -Activity "Siliniyor..." -Completed
# ── 10. HATA RAPORU ──────────────────────────────────────────────
if ($failedItems.Count -gt 0) {
$errText = @"
================================================================
SİLME İŞLEMİ — HATA RAPORU
Tarih: $(Get-Date -Format "dd.MM.yyyy HH:mm:ss")
================================================================
Kaynak Konum : $sourceLocation
Başarılı silinen : $deletedCount / $($allFiles.Count)
Başarısız : $($failedItems.Count)
BAŞARISIZ DOSYALAR:
$(foreach ($fi in $failedItems) { " $($fi.Path)`n -> $($fi.Error)`n" })
================================================================
"@
$errPath = Join-Path $desktop "Silme_Hata_Raporu_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
Set-Content -LiteralPath $errPath -Value $errText -Encoding UTF8
}
# ── 11. HTML RAPORU ──────────────────────────────────────────────
$statusColor = if ($failedItems.Count -eq 0) { "#27ae60" } else { "#e67e22" }
$statusText = if ($failedItems.Count -eq 0) { "TAMAMLANDI" } else { "KISMİ ($($failedItems.Count) hata)" }
$hashRows = ""
$displayFiles = $deletedFiles | Select-Object -First 50
foreach ($f in $displayFiles) {
$hashRows += "<tr><td>$($f.Name)</td><td>$([math]::Round($f.Length/1KB,2)) KB</td>" +
"<td class='mono'>$($hashTable[$f.FullName])</td></tr>`n"
}
if ($deletedFiles.Count -gt 50) {
$hashRows += "<tr><td colspan='3' style='text-align:center;color:#888;'>... ve $($deletedFiles.Count - 50) dosya daha</td></tr>"
}
$failedRows = ""
foreach ($fi in $failedItems) {
$failedRows += "<tr><td>$($fi.Path)</td><td style='color:#c0392b;'>$($fi.Error)</td></tr>`n"
}
$recoveryInfo = if ($useRecycleBin) {
"<div class='info-box success'>Bu dosyalar Geri Dönüşüm Kutusu'na gönderildi.`n" +
"Geri getirmek için: Geri Dönüşüm Kutusu'nu açın -> Dosyaları seçin -> 'Geri Yükle' deyin.</div>"
} else {
"<div class='info-box danger'>Bu dosyalar KALICI olarak silindi. Geri getirilemez.</div>"
}
$html = @"
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<title>Silme İşlem Raporu</title>
<style>
*{box-sizing:border-box}
body{font-family:'Segoe UI',Tahoma,sans-serif;background:#f0f2f5;margin:0;padding:30px}
.card{max-width:900px;margin:auto;background:#fff;border-radius:10px;
box-shadow:0 6px 20px rgba(0,0,0,.08);overflow:hidden}
.header{background:linear-gradient(135deg,#c0392b,#e74c3c);color:#fff;padding:28px 32px}
.header h1{margin:0;font-size:1.5em}
.header .badge{display:inline-block;margin-top:8px;padding:4px 14px;
border-radius:20px;font-weight:700;font-size:.9em;background:$statusColor}
.body{padding:28px 32px}
table{width:100%;border-collapse:collapse;margin:18px 0}
th,td{padding:10px 14px;border:1px solid #e0e0e0;text-align:left}
th{background:#c0392b;color:#fff}
tr:nth-child(even){background:#f9fbfd}
.mono{font-family:Consolas,monospace;font-size:.8em;word-break:break-all}
.hash-box{background:#ecf0f1;padding:14px;border-radius:6px;margin:10px 0}
.info-box{padding:14px;border-radius:6px;margin:14px 0;white-space:pre-line;font-size:.95em}
.info-box.success{background:#d4edda;color:#155724;border-left:4px solid #27ae60}
.info-box.danger{background:#f8d7da;color:#721c24;border-left:4px solid #c0392b}
.footer{text-align:center;color:#aaa;font-size:.8em;padding:16px}
</style>
</head>
<body>
<div class="card">
<div class="header">
<h1>Silme İşlem Raporu</h1>
<span class="badge">$statusText</span>
</div>
<div class="body">
<table>
<tr><th>Metrik</th><th>Değer</th></tr>
<tr><td>Tarih / Saat</td><td>$(Get-Date -Format "dd.MM.yyyy HH:mm:ss")</td></tr>
<tr><td>Kaynak Konum</td><td><strong>$sourceLocation</strong></td></tr>
<tr><td>Silme Yöntemi</td><td><strong>$modeLabel</strong></td></tr>
<tr><td>Toplam Dosya</td><td>$($allFiles.Count)</td></tr>
<tr><td>Başarıyla Silinen</td><td>$deletedCount</td></tr>
<tr><td>Başarısız</td><td>$($failedItems.Count)</td></tr>
<tr><td>Toplam Boyut</td><td>$totalMB MB ($totalBytes bayt)</td></tr>
<tr><td>Geçen Süre</td><td>$([math]::Round($totalSeconds,2)) saniye</td></tr>
</table>
$recoveryInfo
<h3>Bütünlük Kanıtı (SHA-256)</h3>
<div class="hash-box mono">$finalHash</div>
<h3>Silinen Dosyaların Detayları</h3>
<table>
<tr><th>Dosya Adı</th><th>Boyut</th><th>SHA-256</th></tr>
$hashRows
</table>
$(if ($failedItems.Count -gt 0) {
"<h3>Silinemedi</h3><table><tr><th>Yol</th><th>Hata</th></tr>$failedRows</table>"
})
</div>
<div class="footer">Güvenli Silme Betiği v1.2 — $(Get-Date -Format "yyyy")</div>
</div>
</body>
</html>
"@
$htmlPath = Join-Path $desktop "Silme_Raporu_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
Set-Content -LiteralPath $htmlPath -Value $html -Encoding UTF8
$b64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($html))
$b64Path = Join-Path $desktop "Silme_Raporu_HTML64_$(Get-Date -Format 'yyyyMMdd_HHmmss').b64"
Set-Content -LiteralPath $b64Path -Value $b64 -Encoding UTF8
# ── 12. BİTİŞ BİLDİRİMİ ──────────────────────────────────────────
$summary = "Silme işlemi tamamlandı!`n`n" +
"Silinen: $deletedCount / $($allFiles.Count)`n" +
"Kaynak: $sourceLocation`n" +
"Boyut: $totalMB MB`n" +
"Yöntem: $modeLabel`n`n" +
"Rapor masaüstüne kaydedildi."
if ($failedItems.Count -gt 0) {
$summary += "`n`nUyarı: $($failedItems.Count) dosya silinemedi."
}
if ($useRecycleBin) {
$summary += "`n`nBilgi: Geri almak için Geri Dönüşüm Kutusu'nu açın."
}
[System.Windows.Forms.MessageBox]::Show($summary, "Silme İşlemi Tamamlandı", "OK", "Information")
}
catch {
$errReport = @"
================================================================
KRİTİK HATA — SİLME İŞLEMİ
Tarih: $(Get-Date -Format "dd.MM.yyyy HH:mm:ss")
================================================================
İşlem güvenlik nedeniyle DURDURULDU.
HATA : $($_.Exception.Message)
KONUM: $($_.InvocationInfo.PositionMessage)
YIĞIN: $($_.ScriptStackTrace)
================================================================
"@
$critPath = Join-Path $desktop "Silme_Kritik_Hata_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
Set-Content -LiteralPath $critPath -Value $errReport -Encoding UTF8
[System.Windows.Forms.MessageBox]::Show(
"Kritik hata — işlem güvenli şekilde durduruldu.`n`n$critPath",
"Hata", "OK", "Error"
)
}
AÇIKLAMA :
Kopyalama/Taşıma Betiği (v2.2) Özellikleri
1.Yönetici yetkisi kontrolü ve otomatik yükseltme
2.GUI tabanlı kaynak ve hedef konum seçimi (Windows diyalog pencereleri)
3.Klasör veya dosya seçimi desteği
4.Tekli veya çoklu dosya seçimi
5.Kopyalama veya taşıma işlemi seçimi
6.Gerçek zamanlı hız göstergesi (MB/sn cinsinden)
7.İlerleme çubuğu ile dosya bazlı takip
8.SHA-256 hash hesaplama ile bütünlük doğrulama
9.Kritik sistem yolları koruması (Windows, System32, Program Files vb.)
10.Sürücü kök dizinleri koruması (C:, D:\ vb.)
11.Klasör seçildiğinde klasörün kendisi de dahil kopyalama/taşıma
12.Taşıma sonrası boş kalan dizinlerin otomatik temizliği
13.Hata durumunda işlemi güvenli şekilde durdurma
14.Detaylı HTML rapor oluşturma
15.Base64 kodlanmış HTML yedek raporu (HTML64)
16.Hata durumunda detaylı TXT hata raporu
Güvenli Silme Betiği (v1.2) Özellikleri
1.Yönetici yetkisi kontrolü ve otomatik yükseltme
2.GUI tabanlı silinecek nesne seçimi
3.Klasör veya dosya seçimi desteği
4.Tekli veya çoklu dosya seçimi
5.Geri dönüşüm kutusuna gönderme veya kalıcı silme seçimi
6.Silme öncesi detaylı önizleme penceresi
7.Kalıcı silme için çift onay mekanizması
8.SHA-256 hash hesaplama ile silinen dosyaların kanıtlanması
9.Kritik sistem yolları koruması (Windows, System32, Program Files vb.)
10.Sürücü kök dizinleri koruması (C:, D:\ vb.)
11.Klasör seçildiğinde klasörün kendisi ve içindekilerin silinmesi
12.Boş kalan dizinlerin otomatik temizliği
13.Geri dönüşüm kutusu desteği (yanlışlıkta kurtarma şansı)
14.Hata durumunda diğer dosyalara devam etme (izolasyon)
15.Detaylı HTML rapor oluşturma (kaynak konum bilgisi dahil)
16.Base64 kodlanmış HTML yedek raporu (HTML64)
17.Hata durumunda detaylı TXT hata raporu
18.Kritik hata durumunda işlemi güvenli şekilde durdurma
İki Betiğin Ortak Özellikleri :
1.Windows 10/11 uyumlu
2.Türkçe karakter desteği
3.Hata yönetimi ve raporlama sistemi
4.Masaüstüne otomatik rapor kaydetme
5.Sistem güvenliği öncelikli tasarım
ÖRNEK ÇIKTI EKRAN GÖRÜNTÜSÜ : (Silme)
Güle güle kullanın...
Son düzenleme: