mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
1602 字
8 分钟
PowerShell+ImageMagick:一键自动化设置 Windows 文件夹封面

个人需求:没啥顺手的漫画阅读器。有个叫 Rulia 的我还蛮喜欢,但作者创业去了,久未更新,且一直不支持读取文件夹图片(Cover)的功能。试了个连 Kavita 的插件,压根连不上。

于是转念一想:如果直接修改 Windows 文件夹图标,资源管理器不就是最好的书架吗?

虽然市面上有改压缩包封面的工具,但这不太符合我“解压即看”的习惯。所以我决定自己写个脚本,利用 PowerShell 结合 ImageMagick 来自动化这个过程。ImageMagick 负责高性能的图片裁剪(处理成正方形封面),PowerShell 负责与 Windows 底层交互(写入配置、刷新缓存)。

前置准备#

本方案依赖命令行图像处理工具,请先完成安装:

  1. 下载 ImageMagick:
    • 前往 ImageMagick 官网 下载 Windows 版本。
    • 推荐下载:ImageMagick-x.x.x-Q16-HDRI-x64-dll.exe
  2. 关键安装步骤:
    • 安装过程中,务必勾选以下两项,否则脚本无法运行:
      • Install legacy utilities (e.g. convert)
      • Add application directory to your system path

第一步:核心逻辑脚本 (Set-FolderCover.ps1)#

在任意位置(建议固定目录,如 C:\Scripts\FolderCover)创建文件 Set-FolderCover.ps1

脚本功能升级点:

  • 智能裁剪:调用 ImageMagick 进行“中心 1:1 裁剪”,保留图片主体。
  • 强制刷新:内置 C# 方法调用 Windows API (SHChangeNotify),无需重启资源管理器即可看到封面变化
  • 错误日志:自动记录失败原因到文档目录。
Terminal window
param (
[string[]]$TargetItem
)
# 1. 强制 UTF-8 输出
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# --- 配置 ---
$LogFile = [System.IO.Path]::Combine([Environment]::GetFolderPath("MyDocuments"), "FolderIcon_Debug.log")
$ImageExtensions = @(".jpg", ".jpeg", ".png", ".bmp", ".webp", ".tif", ".tiff")
# --- Win32 API ---
$code = @"
[System.Runtime.InteropServices.DllImport("Shell32.dll")]
public static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
"@
try { $Win32 = Add-Type -MemberDefinition $code -Name "Win32SHChangeNotify" -Namespace Win32Functions -PassThru } catch {}
# --- 日志 ---
function Write-Log {
param ([string]$Message, [string]$Level = "INFO")
$Timestamp = Get-Date -Format "HH:mm:ss"
$LogEntry = "[$Timestamp] [$Level] $Message"
try {
$Encoding = New-Object System.Text.UTF8Encoding($true)
[System.IO.File]::AppendAllText($LogFile, $LogEntry + [Environment]::NewLine, $Encoding)
} catch {}
$Colors = @{ "INFO"="White"; "WARN"="Yellow"; "ERROR"="Red"; "SUCCESS"="Green" }
$C = if ($Colors.ContainsKey($Level)) { $Colors[$Level] } else { "Gray" }
Write-Host $LogEntry -ForegroundColor $C
}
function Update-Explorer {
Write-Log "发送图标刷新信号..." "INFO"
$null = $Win32::SHChangeNotify(0x08000000, 0, [IntPtr]::Zero, [IntPtr]::Zero)
}
function Set-FolderIcon {
param ([string]$FolderPath, [string]$SourceImagePath)
try {
$FolderPath = (Get-Item -LiteralPath $FolderPath).FullName
$DestPath = [System.IO.Path]::Combine($FolderPath, "folder.ico")
$IniPath = [System.IO.Path]::Combine($FolderPath, "desktop.ini")
Write-Log "处理路径: $FolderPath" "INFO"
# 1. 清理旧文件
foreach ($f in @("folder.ico", "folder.jpg", "desktop.ini")) {
$p = [System.IO.Path]::Combine($FolderPath, $f)
if (Test-Path -LiteralPath $p) {
Start-Process -FilePath "attrib.exe" -ArgumentList "-s -h -r `"$p`"" -WindowStyle Hidden -Wait
Remove-Item -LiteralPath $p -Force -ErrorAction SilentlyContinue
}
}
# 2. 生成 ICO (ImageMagick)
Write-Log "生成图标..." "INFO"
$argsList = @(
"`"$SourceImagePath`"",
"-resize", "256x256^",
"-gravity", "center",
"-extent", "256x256",
"-define", "icon:auto-resize=256,128,64,48,32,16",
"`"$DestPath`""
)
$proc = Start-Process -FilePath "magick" -ArgumentList $argsList -WindowStyle Hidden -Wait -PassThru
if ($proc.ExitCode -ne 0) { throw "Magick 转换失败" }
# 3. 写入 desktop.ini (最简版)
Write-Log "配置 desktop.ini..." "INFO"
# 只保留核心的一行
$iniContent = "[.ShellClassInfo]`r`nIconResource=folder.ico,0"
# 依然使用 UTF-8 (PowerShell 默认带 BOM)
Set-Content -LiteralPath $IniPath -Value $iniContent -Encoding UTF8 -Force
# 4. 强制属性 (Attrib)
Write-Log "应用属性..." "INFO"
Start-Process -FilePath "attrib.exe" -ArgumentList "+s +h `"$DestPath`"" -WindowStyle Hidden -Wait
Start-Process -FilePath "attrib.exe" -ArgumentList "+s +h `"$IniPath`"" -WindowStyle Hidden -Wait
Start-Process -FilePath "attrib.exe" -ArgumentList "+r `"$FolderPath`"" -WindowStyle Hidden -Wait
# 5. 时间戳刷新
(Get-Item -LiteralPath $IniPath -Force).LastWriteTime = Get-Date
Write-Log "成功。" "SUCCESS"
}
catch {
Write-Log "错误: $($_.Exception.Message)" "ERROR"
}
}
# --- 主入口 ---
try {
# 合并参数以支持多选
$AllPaths = @()
if ($TargetItem) { $AllPaths += $TargetItem }
if ($args) { $AllPaths += $args }
$AllPaths = $AllPaths | Select-Object -Unique | ForEach-Object { $_.Trim().Trim('"') }
if ($AllPaths.Count -eq 0) { exit }
foreach ($RawPath in $AllPaths) {
if (-not (Test-Path -LiteralPath $RawPath)) { continue }
if (Test-Path -LiteralPath $RawPath -PathType Container) {
# 文件夹模式: 避开 folder.ico 和 folder.jpg
$img = Get-ChildItem -LiteralPath $RawPath -File | Where-Object {
$ImageExtensions -contains $_.Extension.ToLower() -and $_.Name -notmatch "^folder\.(ico|jpg)$"
} | Select-Object -First 1
if ($img) { Set-FolderIcon -FolderPath $RawPath -SourceImagePath $img.FullName }
}
else {
# 图片模式
$parent = Split-Path -Path $RawPath -Parent
Set-FolderIcon -FolderPath $parent -SourceImagePath $RawPath
}
}
Update-Explorer
}
catch {
Write-Log "Main Crash: $_" "ERROR"
}

第二步:注册右键菜单 (Register-RightClick.ps1)#

将此脚本放在与 Set-FolderCover.ps1 相同的目录下。

脚本功能:

  • 自动识别当前路径,写入注册表。
  • 同时注册到 “文件夹右键”“图片文件右键”
  • 自动提权:双击运行即可,无需手动右键以管理员运行。
Terminal window
# --- 自动提权模块 ---
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
Exit
}
# --- 环境检查 ---
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
$TargetScript = Join-Path -Path $ScriptDir -ChildPath "Set-FolderCover.ps1"
if (-not (Test-Path $TargetScript)) {
Write-Host "错误:未找到主脚本 Set-FolderCover.ps1" -ForegroundColor Red
Write-Host "请确保两个文件在同一目录。"
Pause; Exit
}
if (-not (Get-Command magick -ErrorAction SilentlyContinue)) {
Write-Host "警告:未检测到 'magick' 命令!" -ForegroundColor Yellow
Write-Host "请确保已安装 ImageMagick 且添加到了 PATH 环境变量。"
Write-Host "按任意键继续(如果确认已安装)..."
Pause
}
# --- 注册表操作 ---
$MenuText = "设置纯图封面 (1:1)"
# 使用系统自带图标,也可替换为 .ico 文件路径
$IconPath = "imageres.dll,-68"
function Register-Menu {
param (
[string]$RegPath,
[string]$MenuName
)
$KeyPath = "Registry::HKEY_CLASSES_ROOT\$RegPath\shell\SetFolderCover"
$CommandPath = "$KeyPath\command"
# 1. 创建菜单项
if (-not (Test-Path $KeyPath)) { New-Item -Path $KeyPath -Force | Out-Null }
Set-ItemProperty -Path $KeyPath -Name "(default)" -Value $MenuName
Set-ItemProperty -Path $KeyPath -Name "Icon" -Value $IconPath
# 2. 注入命令 (优先使用 pwsh, 降级使用 powershell)
if (-not (Test-Path $CommandPath)) { New-Item -Path $CommandPath -Force | Out-Null }
$Executor = if (Get-Command pwsh -ErrorAction SilentlyContinue) { "pwsh.exe" } else { "powershell.exe" }
$Command = "$Executor -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$TargetScript``" `"%1`""
Set-ItemProperty -Path $CommandPath -Name "(default)" -Value $Command
}
try {
Write-Host "正在注入注册表..." -ForegroundColor Cyan
# 注册位置 1: 文件夹背景/图标右键
Register-Menu -RegPath "Directory" -MenuName $MenuText
# 注册位置 2: 所有图片格式右键
Register-Menu -RegPath "SystemFileAssociations\image" -MenuName "设为当前文件夹封面 (1:1)"
Write-Host "✅ 注册成功!" -ForegroundColor Green
Write-Host "现在你可以右键文件夹或图片使用了。"
}
catch {
Write-Host "❌ 注册失败:$_" -ForegroundColor Red
}
Pause

使用指南#

  1. 部署
  • 将上述两个 .ps1 文件放在同一永久目录(如 D:\Tools\FolderCover\)。
  • 双击运行 Register-RightClick.ps1(会自动请求管理员权限)。
  1. 操作
  • 方法 A:在资源管理器中,右键点击某个漫画文件夹 -> 选择 设置纯图封面 (1:1)
  • 方法 B:进入文件夹,右键点击你喜欢的某张图片 -> 选择 设为当前文件夹封面 (1:1)
  1. 批量处理
  • 选中几百个文件夹,右键一次性执行,脚本会自动为每个文件夹找第一张图做封面。

效果原理#

脚本的核心在于这一行 ImageMagick 命令:

Terminal window
magick "input.jpg" -gravity center -extent "%[fx:w<h?w:h]x%[fx:w<h?w:h]" "folder.jpg"

它利用 fx 表达式动态计算宽高,取较小值作为边长,配合 center 重心,实现智能正方形裁切。相比直接缩放,这样能最大程度保留封面的人物主体,在书架视图下也更整齐美观。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

PowerShell+ImageMagick:一键自动化设置 Windows 文件夹封面
http://www.rinhonlc.fun/posts/windows-folder-cover-automation/
作者
Rinhon
发布于
2025-12-29
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

封面
Sample Song
Sample Artist
封面
Sample Song
Sample Artist
0:00 / 0:00