Windows İkon Değiştirme v1.0 PS1 Betiği

Programlama ve Script dilleri konusunda bilgi paylaşım alanıdır.
Cevapla
Kullanıcı avatarı
TRWE_2012
Zettabyte1
Zettabyte1
Mesajlar: 15670
Kayıt: 25 Eyl 2013, 13:38
cinsiyet: Erkek
Teşekkür etti: 2742 kez
Teşekkür edildi: 5669 kez

Windows İkon Değiştirme v1.0 PS1 Betiği

Mesaj gönderen TRWE_2012 »

Merhabalar

Bu betiğin ilham verici kaynağı , @Tarkan_dost'un kendisi.Bir zamanlar forum'da şöyle bir mesjına denk gelmiştim...

"Hintli aptallar...!!, İşletim sistemini zırt-pırt değiştirip duruyorlar, artık sistem klasörlerinin simgesini değiştiremiyorum"


Bu forum mesajı uzun bir zamandır aklımın bir köşesindeydi.

Ve hasıl kelam aşağıdaki betiği tasarladım.

Change-Icon.TR.ps1

Kod: Tümünü seç

<#
.SYNOPSIS
    Windows'un yerel iletişim kutularını kullanarak bir klasörün, bir kısayol
    (.lnk) dosyasının veya bir dosya türünün (uzantıya göre) ikonunu değiştirir.

.DESCRIPTION
    Bu betik, kullanıcının standart Windows iletişim pencereleri aracılığıyla
    dört hedef türünden birini, ardından bir ikon kaynağı dosyası seçmesini
    sağlar ve seçilen ikonu güvenli biçimde uygular:

      - KLASÖR            -> klasörün içinde bir "desktop.ini" dosyası
                              oluşturur veya günceller ve [.ShellClassInfo]
                              bölümüne IconResource değerini yazar; ardından
                              Windows Gezgini'nin ikonu tanıyıp
                              görüntüleyebilmesi için gerekli Hidden/System
                              özniteliklerini ayarlar. Bu, özel klasör
                              ikonları için Windows tarafından resmi olarak
                              desteklenen yöntemdir ve klasörün içeriğini
                              veya izinlerini değiştirmez.

      - KLASÖR KISAYOLU   -> bir klasöre veya bir programa işaret eden .lnk
        / KISAYOL            dosyasının yalnızca IconLocation özelliğini
                              WScript.Shell COM nesnesi aracılığıyla
                              günceller. Kısayolun hedef yolu ve
                              parametreleri değiştirilmez.

      - HERHANGİ BİR DOSYA (türe göre) -> Windows, sıradan tek bir dosyaya
                              benzersiz bir ikon atamayı desteklemez; normal
                              bir dosyanın ikonu her zaman dosya türüne
                              (uzantısına) göre belirlenir. "Bu nesnenin
                              ikonunu değiştir" isteğine en yakın karşılık
                              olarak, bu seçenek
                              HKEY_CURRENT_USER\Software\Classes\<uzantı>\DefaultIcon
                              altında kullanıcıya özel bir DefaultIcon
                              geçersiz kılması yazar. Bu, yalnızca geçerli
                              Windows kullanıcısı için, aynı uzantıya sahip
                              TÜM dosyaların ikonunu değiştirir. Bu, o dosya
                              türünün varsayılan uygulamasını/işleyicisini
                              DEĞİŞTİRMEZ - yalnızca görüntülenen ikonu
                              değiştirir. Sistem geneli (HKEY_LOCAL_MACHINE)
                              veya tüm kullanıcıları etkileyen hiçbir ayara
                              dokunulmaz ve Yönetici hakkı gerekmez. Bu
                              değişiklik uygulanmadan önce kullanıcı
                              uyarılır ve onay istenir.

    Hiçbir dosya silinmez, hiçbir varsayılan uygulama ilişkilendirmesi
    değiştirilmez ve hiçbir sistem servisine veya sürücüsüne dokunulmaz.
    Yönetici hakkı yalnızca KLASÖR veya KISAYOL hedefi korumalı bir konumda
    (örneğin C:\Windows veya C:\Program Files altında) ise gerekebilir.

    Seçilen ikon kaynağı bir .exe veya .dll dosyası olduğunda, betik
    shell32.dll'in ExtractIconEx API'sini kullanarak o dosyanın içindeki
    her ikonu okur ve tıklanabilir görsel bir galeri olarak gösterir; böylece
    kullanıcı bir ikon indeksi tahmin etmek yerine tam istediği ikonu seçebilir.
    İkonlar herhangi bir nedenle listelenemezse, betik basit bir sayısal
    ikon indeksi istemine geri döner.

.NOTES
    Windows PowerShell 5.1 ve PowerShell 7.x ile uyumludur.
    Tüm çalıştırmalar, Masaüstündeki tek bir kalıcı günlük dosyasına
    ("IconChangeLog.txt") eklenir. Her çalıştırmada yeni bir günlük dosyası
    oluşturmak yerine, çalıştırmalar arasına bir ayraç satırı yazılır.
    Performans için, ikon galerisi bir .exe/.dll dosyasında bulunan en fazla
    ilk 300 ikonu gösterir.
#>

# ----------------------------------------------------------------------------
# Konsol kodlama ayarı (hem Windows PowerShell 5.1 hem PowerShell 7+ için güvenli)
# ----------------------------------------------------------------------------
try { chcp 65001 > $null } catch {}
try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {}

# ----------------------------------------------------------------------------
# İletişim kutuları ve ikon indeksi giriş kutusu için gerekli derlemeleri yükle
# ----------------------------------------------------------------------------
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName Microsoft.VisualBasic

# ----------------------------------------------------------------------------
# Seçilen .exe/.dll dosyasının içindeki ikonları görsel olarak önizlemek için
# kullanılan yerel ikon çıkarma yardımcısı (shell32.dll üzerinden P/Invoke)
# ----------------------------------------------------------------------------
$script:IconExtractionAvailable = $true
try {
    Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;

public class IconExtractorHelper
{
    [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern int ExtractIconEx(string lpszFile, int nIconIndex, IntPtr[] phiconLarge, IntPtr[] phiconSmall, int nIcons);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern bool DestroyIcon(IntPtr hIcon);

    public static int GetIconCount(string filePath)
    {
        return ExtractIconEx(filePath, -1, null, null, 0);
    }
}
"@ -ErrorAction Stop
}
catch {
    $script:IconExtractionAvailable = $false
}

# ----------------------------------------------------------------------------
# Masaüstünde kalıcı günlük dosyası (çalıştırmalar arasında tek dosyaya eklenir)
# ----------------------------------------------------------------------------
$DesktopPath = [Environment]::GetFolderPath("Desktop")
$LogFile = Join-Path $DesktopPath "IconChangeLog.txt"
$logFileExistedBefore = Test-Path $LogFile

function Write-Log {
    param([string]$Message)
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $line = "[$timestamp] $Message"
    Add-Content -Path $LogFile -Value $line -Encoding UTF8
    Write-Host $Message
}

function Write-LogSeparator {
    Add-Content -Path $LogFile -Value "" -Encoding UTF8
    Add-Content -Path $LogFile -Value ("*" * 24) -Encoding UTF8
    Add-Content -Path $LogFile -Value "" -Encoding UTF8
}

if ($logFileExistedBefore) {
    Write-LogSeparator
}

# ----------------------------------------------------------------------------
# Yardımcı fonksiyon: Oturumun yönetici (Administrator) olarak yükseltilip
# yükseltilmediğini kontrol eder
# ----------------------------------------------------------------------------
function Test-IsAdmin {
    $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = New-Object Security.Principal.WindowsPrincipal($identity)
    return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}

# ----------------------------------------------------------------------------
# Yardımcı fonksiyon: hedef türünü seçmek için özel dört butonlu pencere
#   Klasör          -> gerçek bir klasör (desktop.ini kullanılır)
#   Klasör Kısayolu -> bir klasöre işaret eden .lnk dosyası (IconLocation kullanılır)
#   Kısayol         -> bir programa/uygulamaya işaret eden .lnk dosyası (IconLocation kullanılır)
#   Herhangi Bir Dosya -> bir dosya TÜRÜNÜN/uzantısının ikonunu değiştirir (registry)
# ----------------------------------------------------------------------------
function Show-TargetTypeDialog {
    $form = New-Object System.Windows.Forms.Form
    $form.Text = "Hedef Türünü Seçin"
    $form.Size = New-Object System.Drawing.Size(580, 160)
    $form.StartPosition = "CenterScreen"
    $form.FormBorderStyle = "FixedDialog"
    $form.MaximizeBox = $false
    $form.MinimizeBox = $false
    $form.TopMost = $true

    $label = New-Object System.Windows.Forms.Label
    $label.Text = "Neyin ikonunu değiştirmek istiyorsunuz?"
    $label.AutoSize = $false
    $label.Size = New-Object System.Drawing.Size(540, 30)
    $label.Location = New-Object System.Drawing.Point(15, 15)
    $form.Controls.Add($label)

    $script:selectedTargetKind = $null

    $btnFolder = New-Object System.Windows.Forms.Button
    $btnFolder.Text = "Klasör"
    $btnFolder.Size = New-Object System.Drawing.Size(125, 45)
    $btnFolder.Location = New-Object System.Drawing.Point(15, 60)
    $btnFolder.Add_Click({ $script:selectedTargetKind = "Folder"; $form.Close() })
    $form.Controls.Add($btnFolder)

    $btnFolderShortcut = New-Object System.Windows.Forms.Button
    $btnFolderShortcut.Text = "Klasör Kısayolu"
    $btnFolderShortcut.Size = New-Object System.Drawing.Size(125, 45)
    $btnFolderShortcut.Location = New-Object System.Drawing.Point(150, 60)
    $btnFolderShortcut.Add_Click({ $script:selectedTargetKind = "FolderShortcut"; $form.Close() })
    $form.Controls.Add($btnFolderShortcut)

    $btnShortcut = New-Object System.Windows.Forms.Button
    $btnShortcut.Text = "Kısayol"
    $btnShortcut.Size = New-Object System.Drawing.Size(125, 45)
    $btnShortcut.Location = New-Object System.Drawing.Point(285, 60)
    $btnShortcut.Add_Click({ $script:selectedTargetKind = "Shortcut"; $form.Close() })
    $form.Controls.Add($btnShortcut)

    $btnFileType = New-Object System.Windows.Forms.Button
    $btnFileType.Text = "Herhangi Bir Dosya"
    $btnFileType.Size = New-Object System.Drawing.Size(125, 45)
    $btnFileType.Location = New-Object System.Drawing.Point(420, 60)
    $btnFileType.Add_Click({ $script:selectedTargetKind = "FileType"; $form.Close() })
    $form.Controls.Add($btnFileType)

    $form.ShowDialog() | Out-Null
    $form.Dispose()

    return $script:selectedTargetKind
}

# ----------------------------------------------------------------------------
# Yardımcı fonksiyon: bir .exe/.dll dosyasının içindeki her ikonu tıklanabilir
# bir galeri olarak gösterir, böylece kullanıcı görsel olarak seçim yapabilir.
# Seçilen ikon indeksini döndürür; kullanıcı iptal ederse $null döner. İkonlar
# listelenemezse (örn. ExtractIconEx kullanılamıyorsa) basit bir sayısal
# istem gösterilir.
# ----------------------------------------------------------------------------
function Show-IconPickerDialog {
    param([string]$FilePath)

    $maxIconsToShow = 300
    $iconCount = 0

    if ($script:IconExtractionAvailable) {
        try {
            $iconCount = [IconExtractorHelper]::GetIconCount($FilePath)
        }
        catch {
            $iconCount = 0
        }
    }

    if ($iconCount -le 0) {
        # Yedek yöntem: ikonlar otomatik olarak listelenemedi
        $indexInput = [Microsoft.VisualBasic.Interaction]::InputBox(
            "Bu dosyadaki ikonlar otomatik olarak listelenemedi.`nKullanılacak ikon indeksini girin (varsayılan 0):",
            "İkon İndeksi",
            "0"
        )
        if ($indexInput -match '^\d+$') { return [int]$indexInput }
        return 0
    }

    $shownCount = [Math]::Min($iconCount, $maxIconsToShow)
    $largeHandles = New-Object IntPtr[] $shownCount
    $smallHandles = New-Object IntPtr[] $shownCount
    [IconExtractorHelper]::ExtractIconEx($FilePath, 0, $largeHandles, $smallHandles, $shownCount) | Out-Null

    $form = New-Object System.Windows.Forms.Form
    $form.Text = "Bir İkon Seçin"
    $form.Size = New-Object System.Drawing.Size(500, 440)
    $form.StartPosition = "CenterScreen"
    $form.TopMost = $true

    $labelText = "Şurada $iconCount ikon bulundu:`n$FilePath"
    if ($iconCount -gt $maxIconsToShow) {
        $labelText += "`n(İlk $maxIconsToShow ikon gösteriliyor)"
    }
    $label = New-Object System.Windows.Forms.Label
    $label.Text = $labelText
    $label.AutoSize = $false
    $label.Size = New-Object System.Drawing.Size(465, 45)
    $label.Location = New-Object System.Drawing.Point(10, 10)
    $form.Controls.Add($label)

    $panel = New-Object System.Windows.Forms.FlowLayoutPanel
    $panel.Location = New-Object System.Drawing.Point(10, 60)
    $panel.Size = New-Object System.Drawing.Size(465, 320)
    $panel.AutoScroll = $true
    $panel.BorderStyle = "FixedSingle"
    $form.Controls.Add($panel)

    $script:selectedIconIdx = $null

    for ($i = 0; $i -lt $shownCount; $i++) {
        $handle = $largeHandles[$i]
        if ($handle -eq [IntPtr]::Zero) { $handle = $smallHandles[$i] }
        if ($handle -eq [IntPtr]::Zero) { continue }

        try {
            $icon = [System.Drawing.Icon]::FromHandle($handle)
            $bmp = $icon.ToBitmap()

            $btn = New-Object System.Windows.Forms.Button
            $btn.Size = New-Object System.Drawing.Size(56, 56)
            $btn.Image = $bmp
            $btn.ImageAlign = [System.Drawing.ContentAlignment]::MiddleCenter
            $btn.Tag = $i
            $btn.Add_Click({ $script:selectedIconIdx = $this.Tag; $form.Close() })
            $panel.Controls.Add($btn)
        }
        catch {
            continue
        }
    }

    $cancelBtn = New-Object System.Windows.Forms.Button
    $cancelBtn.Text = "İptal"
    $cancelBtn.Size = New-Object System.Drawing.Size(100, 30)
    $cancelBtn.Location = New-Object System.Drawing.Point(375, 390)
    $cancelBtn.Add_Click({ $script:selectedIconIdx = $null; $form.Close() })
    $form.Controls.Add($cancelBtn)

    $form.ShowDialog() | Out-Null
    $form.Dispose()

    # Galeri kapandıktan sonra yerel ikon tutamaçlarını serbest bırak
    foreach ($h in $largeHandles) { if ($h -ne [IntPtr]::Zero) { [IconExtractorHelper]::DestroyIcon($h) | Out-Null } }
    foreach ($h in $smallHandles) { if ($h -ne [IntPtr]::Zero) { [IconExtractorHelper]::DestroyIcon($h) | Out-Null } }

    return $script:selectedIconIdx
}

Write-Log "İkon değiştirme betiği başlatıldı."
if (-not (Test-IsAdmin)) {
    Write-Log "UYARI: Betik Yönetici olarak çalışmıyor. Korumalı sistem klasörleri/kısayolları (örn. C:\Windows, C:\Program Files altındaki) için işlem başarısız olabilir."
}

# ----------------------------------------------------------------------------
# Adım 1: Kullanıcıdan değiştirilecek nesnenin türünü sor
#   (Klasör / Klasör Kısayolu / Kısayol / Türe Göre Herhangi Bir Dosya)
# ----------------------------------------------------------------------------
$targetKind = Show-TargetTypeDialog

if (-not $targetKind) {
    Write-Log "Hedef türü seçilmedi. İşlem kullanıcı tarafından iptal edildi."
    Read-Host "`nÇıkmak için ENTER'a basın."
    exit
}

$targetPath = $null
$fileExtension = $null

switch ($targetKind) {
    "Folder" {
        $folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog
        $folderDialog.Description = "İkonunu değiştirmek istediğiniz klasörü seçin"
        $folderDialog.ShowNewFolderButton = $false
        $result = $folderDialog.ShowDialog()
        if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
            $targetPath = $folderDialog.SelectedPath
        }
    }
    "FolderShortcut" {
        $fileDialog = New-Object System.Windows.Forms.OpenFileDialog
        $fileDialog.Title = "Bir klasöre işaret eden kısayol (.lnk) dosyasını seçin"
        $fileDialog.Filter = "Kısayol dosyaları (*.lnk)|*.lnk"
        $fileDialog.CheckFileExists = $true
        $result = $fileDialog.ShowDialog()
        if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
            $targetPath = $fileDialog.FileName
        }
    }
    "Shortcut" {
        $fileDialog = New-Object System.Windows.Forms.OpenFileDialog
        $fileDialog.Title = "İkonunu değiştirmek istediğiniz kısayol (.lnk) dosyasını seçin"
        $fileDialog.Filter = "Kısayol dosyaları (*.lnk)|*.lnk"
        $fileDialog.CheckFileExists = $true
        $result = $fileDialog.ShowDialog()
        if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
            $targetPath = $fileDialog.FileName
        }
    }
    "FileType" {
        $fileDialog = New-Object System.Windows.Forms.OpenFileDialog
        $fileDialog.Title = "Herhangi bir dosya seçin - o dosyanın TÜRÜNÜN ikonu değiştirilecek"
        $fileDialog.Filter = "Tüm dosyalar (*.*)|*.*"
        $fileDialog.CheckFileExists = $true
        $result = $fileDialog.ShowDialog()
        if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
            $targetPath = $fileDialog.FileName
            $fileExtension = [System.IO.Path]::GetExtension($targetPath).ToLower()

            if ([string]::IsNullOrEmpty($fileExtension)) {
                Write-Log "HATA: Seçilen dosyanın uzantısı yok. Windows, dosya uzantısı olmadan türe özel bir ikon atayamaz."
                [System.Windows.Forms.MessageBox]::Show(
                    "Seçilen dosyanın uzantısı yok.`nWindows ikonları dosya uzantısına göre atadığından, bu dosya bu yöntemle hedeflenemez.",
                    "Desteklenmeyen Dosya",
                    [System.Windows.Forms.MessageBoxButtons]::OK,
                    [System.Windows.Forms.MessageBoxIcon]::Warning
                ) | Out-Null
                $targetPath = $null
            }
            else {
                $confirm = [System.Windows.Forms.MessageBox]::Show(
                    "Windows, sıradan tek bir dosya için benzersiz bir ikonu desteklemez.`n`nBu işlem, yalnızca Windows kullanıcı hesabınız için (yalnızca bu tek dosya için değil, bu bilgisayardaki diğer kullanıcılar için de değil) '$fileExtension' uzantısına sahip TÜM dosyaların ikonunu değiştirecektir.`n`nDevam edilsin mi?",
                    "Dosya Türü İkonu Değişimi - Lütfen Onaylayın",
                    [System.Windows.Forms.MessageBoxButtons]::YesNo,
                    [System.Windows.Forms.MessageBoxIcon]::Warning
                )
                if ($confirm -ne [System.Windows.Forms.DialogResult]::Yes) {
                    Write-Log "Dosya türü ikonu değişimi, onay adımında kullanıcı tarafından iptal edildi."
                    $targetPath = $null
                }
            }
        }
    }
}

if (-not $targetPath) {
    Write-Log "Hedef seçilmedi. İşlem kullanıcı tarafından iptal edildi."
    Read-Host "`nÇıkmak için ENTER'a basın."
    exit
}

Write-Log ("Hedef seçildi: {0} (Tür: {1})" -f $targetPath, $targetKind)

# ----------------------------------------------------------------------------
# Adım 2: Kullanıcıdan uygulanacak ikon dosyasını seçmesini iste
# ----------------------------------------------------------------------------
$iconDialog = New-Object System.Windows.Forms.OpenFileDialog
$iconDialog.Title = "Uygulanacak ikon dosyasını seçin"
$iconDialog.Filter = "İkon dosyaları (*.ico)|*.ico|Çalıştırılabilir/Kütüphane dosyaları (*.exe;*.dll)|*.exe;*.dll|Tüm dosyalar (*.*)|*.*"
$iconDialog.CheckFileExists = $true
$iconResult = $iconDialog.ShowDialog()

if ($iconResult -ne [System.Windows.Forms.DialogResult]::OK) {
    Write-Log "İkon dosyası seçilmedi. İşlem kullanıcı tarafından iptal edildi."
    Read-Host "`nÇıkmak için ENTER'a basın."
    exit
}

$iconPath = $iconDialog.FileName
Write-Log "İkon dosyası seçildi: $iconPath"

# ----------------------------------------------------------------------------
# Adım 3: Seçilen dosya .dll veya .exe ise, kullanıcının o dosyadaki tüm
# ikonları görsel bir galeriden seçmesini sağla
# ----------------------------------------------------------------------------
$iconIndex = 0
$extension = [System.IO.Path]::GetExtension($iconPath).ToLower()
if ($extension -eq ".dll" -or $extension -eq ".exe") {
    $pickedIndex = Show-IconPickerDialog -FilePath $iconPath
    if ($null -eq $pickedIndex) {
        Write-Log "'$iconPath' dosyasından ikon seçilmedi. İşlem kullanıcı tarafından iptal edildi."
        Read-Host "`nÇıkmak için ENTER'a basın."
        exit
    }
    $iconIndex = $pickedIndex
}

Write-Log "Kullanılacak ikon indeksi: $iconIndex"

# ----------------------------------------------------------------------------
# Adım 4: İkonu uygula
# ----------------------------------------------------------------------------
try {
    switch ($targetKind) {
        "Folder" {
            # ---- desktop.ini aracılığıyla klasör ikonu değişimi ----
            $desktopIniPath = Join-Path $targetPath "desktop.ini"

            # desktop.ini üzerine yazılabilmesi için varsa mevcut hidden/system/read-only
            # özniteliklerini kaldır
            if (Test-Path $desktopIniPath) {
                attrib -h -s -r "$desktopIniPath" 2>$null
            }

            $iniContent = @"
[.ShellClassInfo]
IconResource=$iconPath,$iconIndex
[ViewState]
Mode=
Vid=
FolderType=Generic
"@
            Set-Content -Path $desktopIniPath -Value $iniContent -Encoding Unicode -Force

            # Gerekli: desktop.ini Hidden + System olmalıdır
            attrib +h +s "$desktopIniPath"

            # Gerekli: Windows Gezgini'nin desktop.ini dosyasını okuyup özel ikonu
            # gösterebilmesi için klasörün kendisi System özniteliğini taşımalıdır
            attrib +s "$targetPath"

            Write-Log "Klasör ikonu başarıyla güncellendi: $targetPath"
            Write-Log "NOT: Yeni ikon hemen görünmüyorsa, Gezgin'de F5'e basın veya oturumu kapatıp yeniden açarak ikon önbelleğini yenileyin."
        }
        { $_ -eq "FolderShortcut" -or $_ -eq "Shortcut" } {
            # ---- WScript.Shell aracılığıyla kısayol ikonu değişimi ----
            $shell = New-Object -ComObject WScript.Shell
            $shortcut = $shell.CreateShortcut($targetPath)
            $shortcut.IconLocation = "$iconPath,$iconIndex"
            $shortcut.Save()
            [System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell) | Out-Null

            Write-Log "Kısayol ikonu başarıyla güncellendi: $targetPath"
        }
        "FileType" {
            # ---- HKEY_CURRENT_USER üzerinden kullanıcıya özel dosya türü ikonu geçersiz kılması ----
            $classesKey = "HKCU:\Software\Classes\$fileExtension"
            $defaultIconKey = "$classesKey\DefaultIcon"

            if (-not (Test-Path $classesKey)) {
                New-Item -Path $classesKey -Force | Out-Null
            }
            if (-not (Test-Path $defaultIconKey)) {
                New-Item -Path $defaultIconKey -Force | Out-Null
            }
            Set-Item -Path $defaultIconKey -Value "$iconPath,$iconIndex"

            Write-Log "'$fileExtension' uzantısı için dosya türü ikonu başarıyla güncellendi (yalnızca geçerli kullanıcı). Örnek dosya: $targetPath"
            Write-Log "NOT: Bu değişiklik, Windows kullanıcı hesabınızdaki '$fileExtension' uzantılı tüm dosyaları etkiler. Yeni ikon hemen görünmüyorsa, Gezgin'de F5'e basın, Gezgin'i yeniden başlatın veya oturumu kapatıp yeniden açarak ikon önbelleğini yenileyin."
        }
    }

    $summaryTarget = if ($targetKind -eq "FileType") { "Dosya türü: $fileExtension (örnek dosya: $targetPath)" } else { $targetPath }

    [System.Windows.Forms.MessageBox]::Show(
        "İkon başarıyla değiştirildi.`n`nHedef: $summaryTarget`nİkon: $iconPath (İndeks: $iconIndex)",
        "Başarılı",
        [System.Windows.Forms.MessageBoxButtons]::OK,
        [System.Windows.Forms.MessageBoxIcon]::Information
    ) | Out-Null
}
catch [System.UnauthorizedAccessException] {
    Write-Log "HATA: Erişim reddedildi. Bu hedef muhtemelen Yönetici hakkı gerektiriyor. Lütfen betiği Yönetici olarak yeniden çalıştırın."
    [System.Windows.Forms.MessageBox]::Show(
        "Erişim reddedildi.`n`nBu hedef değiştirilebilmek için Yönetici hakkı gerektiriyor.`nLütfen betiği Yönetici olarak yeniden çalıştırın.",
        "Erişim Reddedildi",
        [System.Windows.Forms.MessageBoxButtons]::OK,
        [System.Windows.Forms.MessageBoxIcon]::Error
    ) | Out-Null
}
catch {
    Write-Log "HATA: $($_.Exception.Message)"
    [System.Windows.Forms.MessageBox]::Show(
        "Bir hata oluştu:`n`n$($_.Exception.Message)",
        "Hata",
        [System.Windows.Forms.MessageBoxButtons]::OK,
        [System.Windows.Forms.MessageBoxIcon]::Error
    ) | Out-Null
}

Write-Log "İkon değiştirme betiği tamamlandı."
Read-Host "`nÇıkmak için ENTER'a basın."
NOT :

Bu betiğin kötü bir yanı var.Aşağıdaki resme bakın...
Resim
Buradaki "Kullanıcılar" ifadesi varsayılan "Users" ifadesine dönüşüyor ikon değiştirdiğimizde ve bu değişimin geri dönüşü yok.Çok uğraştım olmadı.Böyle kalıyor.

Mesela bir örnek daha.
Resim
Yukarıdaki "Ortak Hesap" ismi Public olarak değişmiştir ikon değişimi sonrası

Eğer bu durum sizin için sorun değilse kullanın, sorun olacaksa kullanmayın...
Cevapla

“Programlama ve Script dilleri” sayfasına dön