web-dev-qa-db-ja.com

Windowsサムネイルを再帰的に自動的に作成するにはどうすればよいですか?

WindowsエクスプローラーでWindows8.1を使用しています。ビデオ、写真、またはその他のそのようなファイルを含むフォルダにアクセスすると、画像キャッシュ( "thumbs.db")が作成されます。絶えず変化する大きなビデオや写真を含む複数のフォルダがあるため、これに問題があります。これらのファイルを含むフォルダーを開くたびに、サムネイルキャッシュが作成されるまで数秒待つ必要があります。

回避策の1つは、サムネイルキャッシュを無効にすることです。しかし、私はサムネイルを見るのが好きなので、これは私にとっての解決策ではありません。代わりに、Windowsサムネイルを再帰的に作成するバッチまたは別のプログラムをx秒ごとに呼び出したいと思います。その後、遅滞なくフォルダを開くことができました。

どうすればこれを達成できますか?

6
dude

これが私が書いた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. が必要になります。

以下を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"

実際には、どのファイル拡張子でも機能するはずです。すべてのディレクトリを再帰的に調べます。 1つの欠点は、一度に1つのファイルタイプしかないことですが、異なるファイル拡張子を使用するだけで複数のジョブを実行できます。基本的に、スクリプトは各ファイルを開き、最初のバイトのみを読み取ります。これは、thumbs.dbファイルを強制的に更新するのに十分です。

編集スクリプトを変更して、上記のシェル更新部分も含めました。テストする画像が何千もありませんが、システムで動作しているようです。これは、ファイルの最初の数バイトの読み取りと、それに続くサムネイルの強制的な更新の両方を組み合わせたものです。

4
Lee Harrison

サムネイルの作成を高速化する2つの方法が考えられます。

  1. サムネイルのサイズを小さくします( 詳細
  2. 新しいファイルのサムネイルを定期的に更新するプログラムを作成する

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 { }
}
2
harrymc

should IThumbnailCache COMインターフェイス(C++)を使用してサムネイルキャッシュを更新する別のプログラムフラグメント。私の知る限り、このタスク用にコンパイル済みのツールはありません。

MSDNによると、「IThumbnailCache :: GetThumbnailのflagsパラメーターにフラグ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();
    }
}
1
user2543253