我使用的是 Windows 8.1 和 Windows 资源管理器。当我访问包含视频、照片或其他此类文件的文件夹时,会创建图像缓存(“thumbs.db”)。我遇到了这个问题,因为我有多个文件夹,里面有不断变化且很大的视频和照片。每次打开包含这些文件的文件夹时,我都必须等待几秒钟,直到创建缩略图缓存。
一种解决方法是禁用缩略图缓存。但我喜欢看缩略图,所以这对我来说不是一个解决方案。相反,我想每隔 x 秒调用一个批处理或另一个程序,以递归方式创建 Windows 缩略图。然后我就可以毫不延迟地打开文件夹。
我怎样才能做到这一点?
答案1
这是我编写的 PowerShell 脚本,它可以完成您的需要。
我从这个帖子中得出了逻辑:https://stackoverflow.com/questions/3555799/how-do-i-refresh-a-files-thumbnail-in-windows-explorer,并将其制作成脚本,可以在windows中作为计划任务运行。
您需要安装 .net4.0 和 PowerShell 3.0 才能使用它,否则会出现错误。此时您可能已经拥有 .net4.0,但您可能需要PowerShell 3.0
将以下内容保存到名为 thumb_generate.ps1 的文件中
param ([string]$path,[string]$ext)
function Refresh-Explorer
{
$code = @'
[System.Runtime.InteropServices.DllImport("Shell32.dll")]
public static extern Int32 SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] String pszName, IntPtr pbc, out IntPtr ppidl, UInt32 sfgaoIn, out UInt32 psfgaoOut);
[System.Runtime.InteropServices.DllImport("Shell32.dll")]
private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
[System.Runtime.InteropServices.DllImport("Shell32.dll")]
private static extern int ILFree(IntPtr pidl);
public static void Refresh(string path) {
uint iAttribute;
IntPtr pidl;
SHParseDisplayName(path, IntPtr.Zero, out pidl, 0, out iAttribute);
SHChangeNotify(0x00002000, 0x1000, IntPtr.Zero, IntPtr.Zero);
ILFree(pidl);
}
'@
Add-Type -MemberDefinition $code -Namespace MyWinAPI -Name Explorer
[MyWinAPI.Explorer]::Refresh($path)
}
cls
if([System.String]::IsNullOrEmpty($path))
{
Write-Host "Path cannot be empty."
Write-Host "Example: .\thumb_generate.ps1 -path ""C:\"" -ext ""jpg"""
return
}
if([System.String]::IsNullOrEmpty($path))
{
Write-Host "Extension cannot be empty."
Write-Host "Example: .\thumb_generate.ps1 -path ""C:\"" -ext ""jpg"""
return
}
$fileExtension = "*." + $ext
Write-Host -ForegroundColor Green "---Thumbnail generation for Windows 7/8---"
Write-Host -ForegroundColor Green "----PowerShell 3.0 & .Net 4.0 required----"
Write-Host "Path: " $path
Write-Host "Extension: " $fileExtension
Write-Host
if (Test-Path $path)
{
Write-Host "Path Exists, begin generation thumbnails"
$images = [System.IO.Directory]::EnumerateFiles($path,$fileExtension,"AllDirectories")
Foreach($image in $images)
{
try
{
$file = New-Object System.IO.FileInfo($image)
Write-Host $file.FullName
$fStream = $file.Open([System.IO.FileMode]::Open,[System.IO.FileAccess]::Read,[System.IO.FileShare]::None)
$firstbyte = New-Object Byte[] 1
$result = $fStream.Read($firstbyte,0,1)
}
catch
{
Write-Host -ForegroundColor Red "An error occured on file: " + $file.FullName
}
$fStream.Close();
}
Refresh-Explorer
}
else
{
"Path Doesn't Exist, Exiting..."
}
然后使用以下参数从 PowerShell 命令行执行它:
.\thumb_generate.ps1 -path "C:\PathToImages\" -ext "jpg"
实际上,任何文件扩展名都可以。它将递归地查看所有目录。一个缺点是一次只能处理一种文件类型,但可以运行多个仅使用不同文件扩展名的作业。基本上,脚本打开每个文件并只读取第一个字节,这足以强制更新 thumbs.db 文件。
编辑我修改了脚本,使其也包含上面发布的 shell 更新部分。虽然我没有数千张图片可以测试,但它似乎在我的系统上工作正常。这结合了读取文件的前几个字节,然后强制刷新缩略图。
答案2
我能想到两种加速缩略图创建的方法:
- 缩小缩略图的尺寸(更多信息)
- 编写一个程序定期刷新新文件的缩略图
对于第二种方法,我不知道有哪个产品可以做到这一点,所以你需要自己编写一个。这是一个有用的参考: 如何在 Windows 资源管理器中刷新文件的缩略图?。
这篇文章建议并包含一个 C# 程序的源代码,该程序通过读取文件的第一个字节来实现此目的。当程序关闭文件时,Windows 会刷新缩略图。
接受的答案更简单地通知 Windows 文件已更改发布解决方案不需要读取文件。
我的版本(未经测试)是:
public static void refreshThumbnail(string path)
{
try
{
uint iAttribute;
IntPtr pidl;
SHParseDisplayName(path, IntPtr.Zero, out pidl, 0, out iAttribute);
SHChangeNotify(
(uint)ShellChangeNotificationEvents.SHCNE_UPDATEITEM,
(uint)ShellChangeNotificationFlags.SHCNF_FLUSH,
pidl,
IntPtr.Zero);
ILFree(pidl);
}
catch { }
}
答案3
另一个程序片段应该使用 IThumbnailCache COM 接口 (C++) 刷新缩略图缓存。据我所知,没有任何预编译工具可以完成此任务。
MSDN 表示:“如果 IThumbnailCache::GetThumbnail 的标志参数包含标志 WTS_EXTRACT,并且缩略图尚未缓存,则会提取缩略图并将其放置在缓存中”
CoInitialize(NULL);
IThumbnailCache *cache;
HRESULT hr = CoCreateInstance(CLSID_LocalThumbnailCache, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&cache));
if (SUCCEEDED(hr))
{
<loop over files>
{
cache->GetThumbnail(<shell item for file>, <required size>, WTS_EXTRACT, NULL, NULL, NULL);
cache->Release();
}
}
答案4
这个问题相当复杂。最好的办法是专门为此设计一个应用程序。
选项1:
搜索*.jpg、*.avi 等,它们都应该被缓存。
选项 2a:
创建批处理脚本来手动创建缩略图。示例(根据您的需要调整):
mkdir thumbjunk
for f in *.jpg
do convert $f -thumbnail 100x80 thumbjunk/$f.gif
递归地:
find * -prune -name '*.jpg' \
-exec convert '{}' -thumbnail 100x80 thumbjunk/'{}'.gif
选项 2b:
这是用于视频文件的,ffmpeg 是工具。
例子:
ffmpeg -ss 00:01:00 -i testavi.avi -vf 'select=not(mod(n\,1000)),scale=320:240,tile=2x3' testavi.png
对于选项 2,您必须遵守缩略图命名方案,以便生成的输出被视为有效。