# BackupFolder.ps1 - Klasör Yedekleme Scripti # Sağ tık menüsünden veya doğrudan çalıştırma için # UTF-8 with BOM olarak kaydedin param( [Parameter(Mandatory=$true)] [string]$FolderPath ) Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing #region ¦¦ RENK & STİL PALETİ ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ $Colors = @{ Background = [System.Drawing.Color]::FromArgb(18, 18, 28) Surface = [System.Drawing.Color]::FromArgb(28, 28, 42) SurfaceAlt = [System.Drawing.Color]::FromArgb(36, 36, 54) Border = [System.Drawing.Color]::FromArgb(55, 55, 80) Accent = [System.Drawing.Color]::FromArgb(99, 102, 241) AccentHover = [System.Drawing.Color]::FromArgb(129, 132, 255) Success = [System.Drawing.Color]::FromArgb(34, 197, 94) Warning = [System.Drawing.Color]::FromArgb(251, 191, 36) Danger = [System.Drawing.Color]::FromArgb(239, 68, 68) TextPrimary = [System.Drawing.Color]::FromArgb(240, 240, 255) TextSecondary= [System.Drawing.Color]::FromArgb(148, 148, 180) TextMuted = [System.Drawing.Color]::FromArgb(90, 90, 120) LogBg = [System.Drawing.Color]::FromArgb(10, 10, 18) } function New-StyledButton { param( [string]$Text, [System.Drawing.Point]$Location, [System.Drawing.Size]$Size, [System.Drawing.Color]$BgColor, [System.Drawing.Color]$HoverColor, [System.Windows.Forms.DialogResult]$DialogResult = "None" ) $btn = New-Object System.Windows.Forms.Button $btn.Text = $Text $btn.Location = $Location $btn.Size = $Size $btn.FlatStyle = "Flat" $btn.FlatAppearance.BorderSize = 0 $btn.BackColor = $BgColor $btn.ForeColor = [System.Drawing.Color]::FromArgb(240, 240, 255) $btn.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $btn.Cursor = [System.Windows.Forms.Cursors]::Hand # Renkleri Tag'e göm — closure scope sorununu önler $btn.Tag = @{ Normal = $BgColor; Hover = $HoverColor } if ($DialogResult -ne "None") { $btn.DialogResult = $DialogResult } $btn.Add_MouseEnter({ $args[0].BackColor = $args[0].Tag.Hover }) $btn.Add_MouseLeave({ $args[0].BackColor = $args[0].Tag.Normal }) return $btn } #endregion #region ¦¦ GİTIGNORE OKUMA ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ function Get-GitIgnorePatterns { param([string]$FolderPath) $patterns = @() # Klasör içinde ve üst klasörlerde .gitignore ara $searchPath = $FolderPath for ($i = 0; $i -lt 4; $i++) { $gitIgnoreFile = Join-Path $searchPath ".gitignore" if (Test-Path $gitIgnoreFile) { $lines = Get-Content $gitIgnoreFile -Encoding UTF8 -ErrorAction SilentlyContinue foreach ($line in $lines) { $trimmed = $line.Trim() # Yorum satırlarını ve boş satırları atla if ($trimmed -and -not $trimmed.StartsWith("#")) { # Sadece klasör/dosya adı veya pattern olan satırları al $clean = $trimmed.TrimStart("/").TrimEnd("/") if ($clean -and $clean -notmatch "[*?!]") { $patterns += $clean } # Basit glob: node_modules/ gibi elseif ($clean -match "^[\w\.\-]+/?$") { $patterns += $clean.TrimEnd("/") } } } break # İlk bulunan .gitignore yeterli } $parent = Split-Path $searchPath -Parent if (-not $parent -or $parent -eq $searchPath) { break } $searchPath = $parent } return ($patterns | Sort-Object -Unique) } #endregion #region ¦¦ DEV KLASÖR TARAMA ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ # Varsayılan hariç tutulacak klasörler $DefaultExcludedFolders = @( "node_modules", "vendor", "build", "dist", ".git", ".svn", ".hg", "bin", "obj", "__pycache__", ".next", ".nuxt", ".output", "target", "out", ".gradle", "venv", ".venv", "env", "coverage", ".nyc_output" ) function Find-DevFolders { param( [string]$FolderPath, [string[]]$ExcludeList ) $found = @() # Sadece 2 seviye derinliğe kadar tara (performans) foreach ($name in $ExcludeList) { # Root seviye if (Test-Path (Join-Path $FolderPath $name)) { $found += $name continue } # 1 seviye alt $subDirs = Get-ChildItem -Path $FolderPath -Directory -ErrorAction SilentlyContinue foreach ($sub in $subDirs) { if (Test-Path (Join-Path $sub.FullName $name)) { $found += "$($sub.Name)\$name" } } } return ($found | Sort-Object -Unique) } #endregion #region ¦¦ ONAY DİYALOGU ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ function Show-OptionsDialog { param( [string]$FolderName, [string[]]$FoundDevFolders, [string[]]$GitIgnorePatterns, [string[]]$AllExcluded ) $form = New-Object System.Windows.Forms.Form $form.Text = "Yedekleme Ayarlari" $form.Size = New-Object System.Drawing.Size(560, 530) $form.MinimumSize = New-Object System.Drawing.Size(560, 530) $form.StartPosition = "CenterScreen" $form.FormBorderStyle = "FixedDialog" $form.MaximizeBox = $false $form.BackColor = $Colors.Background $form.ForeColor = $Colors.TextPrimary $form.Font = New-Object System.Drawing.Font("Segoe UI", 9) # ¦¦ Başlık paneli $panelHeader = New-Object System.Windows.Forms.Panel $panelHeader.Dock = "Top" $panelHeader.Height = 70 $panelHeader.BackColor = $Colors.Surface $form.Controls.Add($panelHeader) $lblIcon = New-Object System.Windows.Forms.Label $lblIcon.Text = "??" $lblIcon.Location = New-Object System.Drawing.Point(16, 14) $lblIcon.Size = New-Object System.Drawing.Size(40, 40) $lblIcon.Font = New-Object System.Drawing.Font("Segoe UI Emoji", 20) $panelHeader.Controls.Add($lblIcon) $lblTitle = New-Object System.Windows.Forms.Label $lblTitle.Text = "Klasör Yedekleme" $lblTitle.Location = New-Object System.Drawing.Point(62, 12) $lblTitle.Size = New-Object System.Drawing.Size(420, 24) $lblTitle.Font = New-Object System.Drawing.Font("Segoe UI", 13, [System.Drawing.FontStyle]::Bold) $lblTitle.ForeColor= $Colors.TextPrimary $panelHeader.Controls.Add($lblTitle) $lblSubtitle = New-Object System.Windows.Forms.Label $lblSubtitle.Text = $FolderName $lblSubtitle.Location = New-Object System.Drawing.Point(63, 38) $lblSubtitle.Size = New-Object System.Drawing.Size(430, 20) $lblSubtitle.Font = New-Object System.Drawing.Font("Segoe UI", 8) $lblSubtitle.ForeColor = $Colors.TextSecondary $panelHeader.Controls.Add($lblSubtitle) # ¦¦ İçerik alanı $panelBody = New-Object System.Windows.Forms.Panel $panelBody.Location = New-Object System.Drawing.Point(0, 70) $panelBody.Size = New-Object System.Drawing.Size(544, 370) $panelBody.BackColor = $Colors.Background $form.Controls.Add($panelBody) # Dev klasörler bölümü $lblDevTitle = New-Object System.Windows.Forms.Label $lblDevTitle.Text = " ? Geliştirme Klasörleri Tespit Edildi" $lblDevTitle.Location = New-Object System.Drawing.Point(12, 14) $lblDevTitle.Size = New-Object System.Drawing.Size(520, 22) $lblDevTitle.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $lblDevTitle.ForeColor = $Colors.Warning $panelBody.Controls.Add($lblDevTitle) # Dev klasörler listesi kutusu $listBox = New-Object System.Windows.Forms.ListBox $listBox.Location = New-Object System.Drawing.Point(12, 42) $listBox.Size = New-Object System.Drawing.Size(518, 110) $listBox.BackColor = $Colors.LogBg $listBox.ForeColor = $Colors.Warning $listBox.Font = New-Object System.Drawing.Font("Consolas", 8.5) $listBox.BorderStyle = "FixedSingle" $listBox.SelectionMode = "None" foreach ($f in $FoundDevFolders) { $listBox.Items.Add(" ?? $f") | Out-Null } $panelBody.Controls.Add($listBox) # .gitignore bölümü $yGit = 162 if ($GitIgnorePatterns.Count -gt 0) { $lblGitTitle = New-Object System.Windows.Forms.Label $lblGitTitle.Text = " ? .gitignore'dan ek desenler ($($GitIgnorePatterns.Count) adet)" $lblGitTitle.Location = New-Object System.Drawing.Point(12, $yGit) $lblGitTitle.Size = New-Object System.Drawing.Size(520, 20) $lblGitTitle.Font = New-Object System.Drawing.Font("Segoe UI", 8.5) $lblGitTitle.ForeColor = $Colors.Success $panelBody.Controls.Add($lblGitTitle) $txtGit = New-Object System.Windows.Forms.TextBox $txtGit.Location = New-Object System.Drawing.Point(12, ($yGit + 24)) $txtGit.Size = New-Object System.Drawing.Size(518, 55) $txtGit.Multiline = $true $txtGit.ReadOnly = $true $txtGit.BackColor = $Colors.LogBg $txtGit.ForeColor = $Colors.Success $txtGit.Font = New-Object System.Drawing.Font("Consolas", 8) $txtGit.BorderStyle= "FixedSingle" $txtGit.ScrollBars = "Vertical" $txtGit.Text = ($GitIgnorePatterns -join ", ") $panelBody.Controls.Add($txtGit) $yGit += 90 } else { $lblNoGit = New-Object System.Windows.Forms.Label $lblNoGit.Text = " ? .gitignore dosyası bulunamadı" $lblNoGit.Location = New-Object System.Drawing.Point(12, $yGit) $lblNoGit.Size = New-Object System.Drawing.Size(520, 20) $lblNoGit.Font = New-Object System.Drawing.Font("Segoe UI", 8.5) $lblNoGit.ForeColor = $Colors.TextMuted $panelBody.Controls.Add($lblNoGit) $yGit += 28 } # Seçenek başlığı $lblChoose = New-Object System.Windows.Forms.Label $lblChoose.Text = "Ne yapmak istersiniz?" $lblChoose.Location = New-Object System.Drawing.Point(12, ($yGit + 10)) $lblChoose.Size = New-Object System.Drawing.Size(520, 20) $lblChoose.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $lblChoose.ForeColor = $Colors.TextSecondary $panelBody.Controls.Add($lblChoose) # ¦¦ Alt buton alanı $panelFooter = New-Object System.Windows.Forms.Panel $panelFooter.Dock = "Bottom" $panelFooter.Height = 72 $panelFooter.BackColor = $Colors.Surface $form.Controls.Add($panelFooter) $btnSkip = New-StyledButton ` -Text " Dev Klasorleri Atla" ` -Location (New-Object System.Drawing.Point(14, 18)) ` -Size (New-Object System.Drawing.Size(168, 38)) ` -BgColor $Colors.Accent ` -HoverColor $Colors.AccentHover ` -DialogResult "Yes" $panelFooter.Controls.Add($btnSkip) $btnAll = New-StyledButton ` -Text " Tumunu Dahil Et" ` -Location (New-Object System.Drawing.Point(192, 18)) ` -Size (New-Object System.Drawing.Size(160, 38)) ` -BgColor $Colors.SurfaceAlt ` -HoverColor $Colors.Border ` -DialogResult "OK" $panelFooter.Controls.Add($btnAll) $btnCancel = New-StyledButton ` -Text " Iptal" ` -Location (New-Object System.Drawing.Point(362, 18)) ` -Size (New-Object System.Drawing.Size(160, 38)) ` -BgColor ([System.Drawing.Color]::FromArgb(80, 30, 30)) ` -HoverColor $Colors.Danger ` -DialogResult "No" $panelFooter.Controls.Add($btnCancel) $form.AcceptButton = $btnSkip $form.CancelButton = $btnCancel return $form.ShowDialog() } #endregion #region ¦¦ İLERLEME / LOG FORMU ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ $script:ProgressForm = $null $script:ProgressBar = $null $script:LogBox = $null $script:StatusLabel = $null function Show-ProgressForm { param([string]$FolderName) $script:ProgressForm = New-Object System.Windows.Forms.Form $script:ProgressForm.Text = "Yedekleniyor..." $script:ProgressForm.Size = New-Object System.Drawing.Size(560, 420) $script:ProgressForm.StartPosition = "CenterScreen" $script:ProgressForm.FormBorderStyle = "FixedDialog" $script:ProgressForm.MaximizeBox = $false $script:ProgressForm.ControlBox = $false $script:ProgressForm.BackColor = $Colors.Background # Header $panH = New-Object System.Windows.Forms.Panel $panH.Dock = "Top" $panH.Height = 60 $panH.BackColor = $Colors.Surface $script:ProgressForm.Controls.Add($panH) $lblH = New-Object System.Windows.Forms.Label $lblH.Text = "? Yedekleme İşlemi" $lblH.Location = New-Object System.Drawing.Point(14, 10) $lblH.Size = New-Object System.Drawing.Size(530, 24) $lblH.Font = New-Object System.Drawing.Font("Segoe UI", 12, [System.Drawing.FontStyle]::Bold) $lblH.ForeColor = $Colors.TextPrimary $panH.Controls.Add($lblH) $lblSub = New-Object System.Windows.Forms.Label $lblSub.Text = $FolderName $lblSub.Location = New-Object System.Drawing.Point(15, 36) $lblSub.Size = New-Object System.Drawing.Size(500, 18) $lblSub.Font = New-Object System.Drawing.Font("Segoe UI", 8) $lblSub.ForeColor = $Colors.TextSecondary $panH.Controls.Add($lblSub) # Durum etiketi $script:StatusLabel = New-Object System.Windows.Forms.Label $script:StatusLabel.Text = "Başlatılıyor..." $script:StatusLabel.Location = New-Object System.Drawing.Point(14, 72) $script:StatusLabel.Size = New-Object System.Drawing.Size(530, 20) $script:StatusLabel.Font = New-Object System.Drawing.Font("Segoe UI", 9) $script:StatusLabel.ForeColor = $Colors.TextSecondary $script:ProgressForm.Controls.Add($script:StatusLabel) # Progress bar $script:ProgressBar = New-Object System.Windows.Forms.ProgressBar $script:ProgressBar.Location = New-Object System.Drawing.Point(14, 96) $script:ProgressBar.Size = New-Object System.Drawing.Size(526, 18) $script:ProgressBar.Style = "Marquee" $script:ProgressBar.MarqueeAnimationSpeed = 25 $script:ProgressForm.Controls.Add($script:ProgressBar) # Log paneli başlığı $lblLog = New-Object System.Windows.Forms.Label $lblLog.Text = "İşlem Günlüğü" $lblLog.Location = New-Object System.Drawing.Point(14, 124) $lblLog.Size = New-Object System.Drawing.Size(200, 18) $lblLog.Font = New-Object System.Drawing.Font("Segoe UI", 8, [System.Drawing.FontStyle]::Bold) $lblLog.ForeColor = $Colors.TextMuted $script:ProgressForm.Controls.Add($lblLog) # Log kutusu $script:LogBox = New-Object System.Windows.Forms.RichTextBox $script:LogBox.Location = New-Object System.Drawing.Point(14, 146) $script:LogBox.Size = New-Object System.Drawing.Size(526, 200) $script:LogBox.BackColor = $Colors.LogBg $script:LogBox.ForeColor = $Colors.TextSecondary $script:LogBox.Font = New-Object System.Drawing.Font("Consolas", 8.5) $script:LogBox.BorderStyle = "FixedSingle" $script:LogBox.ReadOnly = $true $script:LogBox.ScrollBars = "Vertical" $script:ProgressForm.Controls.Add($script:LogBox) $script:ProgressForm.Show() $script:ProgressForm.Refresh() } function Write-Log { param( [string]$Message, [string]$Level = "INFO" # INFO, OK, WARN, ERR ) if (-not $script:LogBox) { return } $timestamp = Get-Date -Format "HH:mm:ss" $color = switch ($Level) { "OK" { $Colors.Success } "WARN" { $Colors.Warning } "ERR" { $Colors.Danger } default{ $Colors.TextSecondary } } $prefix = switch ($Level) { "OK" { "?" } "WARN" { "?" } "ERR" { "?" } default{ "›" } } $script:LogBox.SelectionStart = $script:LogBox.TextLength $script:LogBox.SelectionLength = 0 $script:LogBox.SelectionColor = $Colors.TextMuted $script:LogBox.AppendText("[$timestamp] ") $script:LogBox.SelectionColor = $color $script:LogBox.AppendText("$prefix $Message`n") $script:LogBox.ScrollToCaret() $script:ProgressForm.Refresh() } function Update-Status { param([string]$Text) if ($script:StatusLabel) { $script:StatusLabel.Text = $Text $script:ProgressForm.Refresh() } } function Close-ProgressForm { if ($script:ProgressForm) { $script:ProgressBar.Style = "Continuous" $script:ProgressBar.Value = 100 Start-Sleep -Milliseconds 400 $script:ProgressForm.Close() $script:ProgressForm = $null } } #endregion #region ¦¦ SONUÇ DİYALOGU ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ function Show-ResultDialog { param( [bool]$Success, [string]$Message, [string]$FilePath = "" ) $form = New-Object System.Windows.Forms.Form $form.Text = if ($Success) { "Yedekleme Tamamlandi" } else { "Hata" } $form.Size = New-Object System.Drawing.Size(500, 240) $form.StartPosition = "CenterScreen" $form.FormBorderStyle = "FixedDialog" $form.MaximizeBox = $false $form.BackColor = $Colors.Background $accentColor = if ($Success) { $Colors.Success } else { $Colors.Danger } $icon = if ($Success) { "?" } else { "?" } # Üst renkli şerit $strip = New-Object System.Windows.Forms.Panel $strip.Dock = "Top" $strip.Height = 5 $strip.BackColor = $accentColor $form.Controls.Add($strip) $lblIcon = New-Object System.Windows.Forms.Label $lblIcon.Text = $icon $lblIcon.Location = New-Object System.Drawing.Point(16, 24) $lblIcon.Size = New-Object System.Drawing.Size(40, 40) $lblIcon.Font = New-Object System.Drawing.Font("Segoe UI", 22, [System.Drawing.FontStyle]::Bold) $lblIcon.ForeColor = $accentColor $form.Controls.Add($lblIcon) $lblMsg = New-Object System.Windows.Forms.Label $lblMsg.Text = $Message $lblMsg.Location = New-Object System.Drawing.Point(62, 24) $lblMsg.Size = New-Object System.Drawing.Size(400, 60) $lblMsg.Font = New-Object System.Drawing.Font("Segoe UI", 9) $lblMsg.ForeColor = $Colors.TextPrimary $form.Controls.Add($lblMsg) if ($FilePath -and $Success) { $lblFile = New-Object System.Windows.Forms.Label $lblFile.Text = $FilePath $lblFile.Location = New-Object System.Drawing.Point(62, 90) $lblFile.Size = New-Object System.Drawing.Size(400, 36) $lblFile.Font = New-Object System.Drawing.Font("Consolas", 8) $lblFile.ForeColor = $Colors.TextSecondary $form.Controls.Add($lblFile) } $btnOK = New-StyledButton ` -Text "Tamam" ` -Location (New-Object System.Drawing.Point(150, 158)) ` -Size (New-Object System.Drawing.Size(120, 36)) ` -BgColor $accentColor ` -HoverColor $Colors.AccentHover ` -DialogResult "OK" $form.Controls.Add($btnOK) if ($FilePath -and $Success) { $script:_ResultFilePath = $FilePath $btnOpen = New-StyledButton ` -Text "Klasoru Ac" ` -Location (New-Object System.Drawing.Point(280, 158)) ` -Size (New-Object System.Drawing.Size(120, 36)) ` -BgColor $Colors.SurfaceAlt ` -HoverColor $Colors.Border $btnOpen.Add_Click({ Start-Process explorer.exe (Split-Path $script:_ResultFilePath -Parent) }) $form.Controls.Add($btnOpen) } $form.AcceptButton = $btnOK $form.ShowDialog() | Out-Null } #endregion #region ¦¦ ANA AKIŞ ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ # Klasör var mı? if (-not (Test-Path $FolderPath)) { Show-ResultDialog -Success $false -Message "Belirtilen klasör bulunamadı:`n$FolderPath" exit 1 } $FolderName = Split-Path $FolderPath -Leaf $OutputDir = Split-Path $FolderPath -Parent # .gitignore desenlerini oku $GitIgnorePatterns = Get-GitIgnorePatterns -FolderPath $FolderPath # Tüm exclusion listesini birleştir $AllExcluded = ($DefaultExcludedFolders + $GitIgnorePatterns) | Sort-Object -Unique # Dev klasörleri tara $FoundDevFolders = Find-DevFolders -FolderPath $FolderPath -ExcludeList $AllExcluded $SkipDevFolders = $false if ($FoundDevFolders.Count -gt 0) { $choice = Show-OptionsDialog ` -FolderName $FolderName ` -FoundDevFolders $FoundDevFolders ` -GitIgnorePatterns $GitIgnorePatterns ` -AllExcluded $AllExcluded switch ($choice) { "No" { exit 0 } # İptal "Yes" { $SkipDevFolders = $true } # Dev klasörlerini atla "OK" { $SkipDevFolders = $false } # Tümünü dahil et default { exit 0 } } } # Arşiv araçlarını tespit et $WinRarPath = "${env:ProgramFiles}\WinRAR\rar.exe" $SevenZipPath= "${env:ProgramFiles}\7-Zip\7z.exe" $UseWinRar = Test-Path $WinRarPath $UseSevenZip = -not $UseWinRar -and (Test-Path $SevenZipPath) $UsePS = -not $UseWinRar -and -not $UseSevenZip # Dosya adı $Date = Get-Date -Format "yyyyMMdd" $Ext = if ($UseWinRar) { "rar" } else { "zip" } $Pattern = "^${FolderName}_${Date}_\d{3}\.$Ext$" $ExistingBackups = Get-ChildItem -Path $OutputDir -Filter "${FolderName}_${Date}_*" | Where-Object { $_.Name -match $Pattern } $NextNumber = 1 if ($ExistingBackups) { $nums = $ExistingBackups.Name | ForEach-Object { if ($_ -match "_(\d{3})\.$Ext$") { [int]$Matches[1] } } | Sort-Object if ($nums) { $NextNumber = ($nums | Select-Object -Last 1) + 1 } } $NumFmt = "{0:D3}" -f $NextNumber $OutputFile = Join-Path $OutputDir "${FolderName}_${Date}_${NumFmt}.$Ext" # İlerleme formunu göster Show-ProgressForm -FolderName $FolderName $tool = if ($UseWinRar) { "WinRAR" } elseif ($UseSevenZip) { "7-Zip" } else { "PowerShell" } Write-Log "Araç: $tool" Write-Log "Kaynak: $FolderPath" Write-Log "Hedef: $OutputFile" if ($SkipDevFolders) { Write-Log "Hariç tutulacak: $($AllExcluded -join ', ')" -Level "WARN" } else { Write-Log "Tüm dosyalar dahil ediliyor" } try { Push-Location $OutputDir if ($UseWinRar) { Update-Status "WinRAR ile sıkıştırılıyor..." Write-Log "WinRAR başlatılıyor..." if ($SkipDevFolders) { # Her exclusion için ayrı -x argümanı oluştur $excludeArgs = $AllExcluded | ForEach-Object { # Hem root hem alt klasör desenleri "-x`"$FolderName\$_\*`"", "-x`"*\$_\*`"" } $argStr = "a -r -ep1 $($excludeArgs -join ' ') `"$OutputFile`" `"$FolderName`"" } else { $argStr = "a -r -ep1 `"$OutputFile`" `"$FolderName`"" } Write-Log "Komut: rar.exe $argStr" $proc = Start-Process -FilePath $WinRarPath -ArgumentList $argStr -Wait -NoNewWindow -PassThru if ($proc.ExitCode -notin @(0, 1)) { throw "WinRAR çıkış kodu: $($proc.ExitCode)" } } elseif ($UseSevenZip) { Update-Status "7-Zip ile sıkıştırılıyor..." Write-Log "7-Zip başlatılıyor..." if ($SkipDevFolders) { $excludeArgs = $AllExcluded | ForEach-Object { "-x!$FolderName\$_", "-xr!$_" } $argStr = "a $($excludeArgs -join ' ') `"$OutputFile`" `"$FolderName`"" } else { $argStr = "a `"$OutputFile`" `"$FolderName`"" } Write-Log "Komut: 7z.exe $argStr" $proc = Start-Process -FilePath $SevenZipPath -ArgumentList $argStr -Wait -NoNewWindow -PassThru if ($proc.ExitCode -ne 0) { throw "7-Zip çıkış kodu: $($proc.ExitCode)" } } else { Update-Status "PowerShell Compress-Archive ile sıkıştırılıyor..." Write-Log "PowerShell Compress-Archive kullanılıyor..." -Level "WARN" if ($SkipDevFolders) { Write-Log "Dosyalar filtreleniyor..." $basePath = Resolve-Path ".\$FolderName" $items = Get-ChildItem -Path ".\$FolderName" -Recurse -Force -ErrorAction SilentlyContinue | Where-Object { $rel = $_.FullName.Substring($basePath.Path.Length).TrimStart("\") $parts = $rel -split "\\" $exclude = $false foreach ($part in $parts) { if ($AllExcluded -contains $part) { $exclude = $true; break } } -not $exclude } if ($items) { Write-Log "$($items.Count) dosya/klasör dahil edilecek" Compress-Archive -Path $items.FullName -DestinationPath $OutputFile -Force } else { throw "Filtre sonrası dahil edilecek dosya kalmadı." } } else { Compress-Archive -Path ".\$FolderName" -DestinationPath $OutputFile -Force } } Pop-Location # Boyut bilgisi $fileInfo = Get-Item $OutputFile -ErrorAction SilentlyContinue $sizeMB = if ($fileInfo) { [math]::Round($fileInfo.Length / 1MB, 2) } else { "?" } Write-Log "Tamamlandi! Boyut: $sizeMB MB" -Level "OK" Update-Status "Tamamlandi!" Start-Sleep -Milliseconds 600 Close-ProgressForm Show-ResultDialog ` -Success $true ` -Message "Yedekleme başarıyla tamamlandı!`nBoyut: $sizeMB MB" ` -FilePath $OutputFile } catch { if ((Get-Location).Path -ne $OutputDir) { Pop-Location } Write-Log "HATA: $($_.Exception.Message)" -Level "ERR" Start-Sleep -Milliseconds 800 Close-ProgressForm Show-ResultDialog -Success $false -Message "Yedekleme sırasında hata oluştu:`n$($_.Exception.Message)" exit 1 } #endregion