📄 通用鼠标安装脚本

ps1
# ============================================================
# Cursor Theme Installer v2.0
# Auto copy cursor files, update registry, apply immediately
# ============================================================

# Check Administrator
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
    Write-Host ""
    Write-Host "========================================================" -ForegroundColor Red
    Write-Host "  [ERROR] Administrator privileges required!" -ForegroundColor Red
    Write-Host "  Right-click script -> Run with PowerShell (as Administrator)" -ForegroundColor Yellow
    Write-Host "========================================================" -ForegroundColor Red
    Write-Host ""
    Read-Host "Press Enter to exit"
    exit 1
}

# ============================================================
# Configuration
# ============================================================

$ThemeName = "MyCursorTheme"
$SourceDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$TargetDir = "$env:windir\Cursors\$ThemeName"

# ============================================================
# File name matching rules (order matters)
# ============================================================

$mappingRules = @(
    @{ Pattern = "Normal|Arrow|aero_arrow|default";         Cursor = "Arrow" },
    @{ Pattern = "Busy|Wait|aero_busy|loading|hourglass";   Cursor = "Wait" },
    @{ Pattern = "Working|AppStarting|aero_working";        Cursor = "AppStarting" },
    @{ Pattern = "Help|aero_helpsel|question";              Cursor = "Help" },
    @{ Pattern = "Precision|Crosshair|aero_cross|cross";    Cursor = "Crosshair" },
    @{ Pattern = "Text|IBeam|aero_ibeam|ibeam";             Cursor = "IBeam" },
    @{ Pattern = "Link|Hand|aero_link|pointer|grab";        Cursor = "Hand" },
    @{ Pattern = "Handwriting|NWPen|aero_pen|pen";          Cursor = "NWPen" },
    @{ Pattern = "Move|SizeAll|aero_move|all";              Cursor = "SizeAll" },
    @{ Pattern = "Horizontal|SizeWE|aero_ew|ew";            Cursor = "SizeWE" },
    @{ Pattern = "Vertical|SizeNS|aero_ns|ns";              Cursor = "SizeNS" },
    @{ Pattern = "Diagonal1|SizeNWSE|aero_nwse|nwse";       Cursor = "SizeNWSE" },
    @{ Pattern = "Diagonal2|SizeNESW|aero_nesw|nesw";       Cursor = "SizeNESW" },
    @{ Pattern = "Unavailable|No|aero_unavail|stop|forbid"; Cursor = "No" },
    @{ Pattern = "Alternate|UpArrow|aero_up|up";            Cursor = "UpArrow" },
    @{ Pattern = "Person";                                  Cursor = "Person" },
    @{ Pattern = "Pin";                                     Cursor = "Pin" }
)

# ============================================================
# Start Installation
# ============================================================

Write-Host ""
Write-Host "========================================================" -ForegroundColor Cyan
Write-Host "        Cursor Theme Installer v2.0" -ForegroundColor Cyan
Write-Host "========================================================" -ForegroundColor Cyan
Write-Host ""

# Step 1: Create directory
Write-Host "[Step 1/4] Creating target directory..." -ForegroundColor Yellow

if (-NOT (Test-Path $TargetDir)) {
    New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null
    Write-Host "  [OK] Created: $TargetDir" -ForegroundColor Green
} else {
    Write-Host "  [INFO] Directory exists: $TargetDir" -ForegroundColor Gray
}

# Step 2: Copy files
Write-Host ""
Write-Host "[Step 2/4] Copying cursor files..." -ForegroundColor Yellow

$files = Get-ChildItem -Path $SourceDir -File | Where-Object { $_.Extension -match "\.ani|\.cur" }

if ($files.Count -eq 0) {
    Write-Host ""
    Write-Host "========================================================" -ForegroundColor Red
    Write-Host "  [ERROR] No .ani or .cur files found!" -ForegroundColor Red
    Write-Host "  Place cursor files in the same directory as this script" -ForegroundColor Yellow
    Write-Host "========================================================" -ForegroundColor Red
    Write-Host ""
    Read-Host "Press Enter to exit"
    exit 1
}

$copiedCount = 0
foreach ($file in $files) {
    $destPath = Join-Path -Path $TargetDir -ChildPath $file.Name
    Copy-Item -Path $file.FullName -Destination $destPath -Force
    $copiedCount++
    Write-Host "  [FILE] $($file.Name)" -ForegroundColor Gray
}

Write-Host "  [OK] Copied $copiedCount files" -ForegroundColor Green

# Step 3: Update registry
Write-Host ""
Write-Host "[Step 3/4] Updating registry..." -ForegroundColor Yellow

$fileList = Get-ChildItem -Path $TargetDir -File
$regPath = "HKCU:\Control Panel\Cursors"
$mappedCount = 0
$unmatched = @()

foreach ($rule in $mappingRules) {
    $matched = $fileList | Where-Object { $_.BaseName -match $rule.Pattern }
    if ($matched) {
        $targetFile = $matched | Select-Object -First 1
        Set-ItemProperty -Path $regPath -Name $rule.Cursor -Value "$TargetDir\$($targetFile.Name)" -Force
        Write-Host "  [OK] $($rule.Cursor) -> $($targetFile.Name)" -ForegroundColor Green
        $mappedCount++
    } else {
        $unmatched += $rule.Cursor
    }
}

Set-ItemProperty -Path $regPath -Name "(default)" -Value $ThemeName -Force

Write-Host ""
Write-Host "  [STATS] Matched: $mappedCount / $($mappingRules.Count)" -ForegroundColor Cyan

if ($unmatched.Count -gt 0) {
    Write-Host "  [WARN] Unmatched: $($unmatched -join ', ')" -ForegroundColor Yellow
}

# Step 4: Refresh cursors
Write-Host ""
Write-Host "[Step 4/4] Refreshing cursors..." -ForegroundColor Yellow

try {
    Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class CursorHelper {
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
    public const int SPI_SETCURSORS = 0x0057;
    public const int SPIF_UPDATEINIFILE = 0x01;
    public const int SPIF_SENDCHANGE = 0x02;
}
"@
    [CursorHelper]::SystemParametersInfo(0x0057, 0, $null, 0x03) | Out-Null
    Write-Host "  [OK] Cursors refreshed" -ForegroundColor Green
} catch {
    Write-Host "  [WARN] Auto-refresh failed, restart Explorer manually" -ForegroundColor Yellow
}

# ============================================================
# Complete
# ============================================================

Write-Host ""
Write-Host "========================================================" -ForegroundColor Green
Write-Host "  [DONE] Installation complete!" -ForegroundColor Green
Write-Host "  Theme: $ThemeName" -ForegroundColor Yellow
Write-Host "  Location: $TargetDir" -ForegroundColor Gray
Write-Host "  Files: $copiedCount" -ForegroundColor Gray
Write-Host "  Mapped: $mappedCount" -ForegroundColor Gray
Write-Host ""
Write-Host "  [TIP] If cursors don't change, restart Explorer" -ForegroundColor Cyan
Write-Host "========================================================" -ForegroundColor Green
Write-Host ""

Read-Host "Press Enter to exit"
← 返回脚本列表