1

IExtractImage インターフェイスをインポートする次のコードがあります。

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1")]
public interface IExtractImage
{
  [PreserveSig]
   Int32 GetLocation([MarshalAs(UnmanagedType.LPWStr)] out StringBuilder pszPathBuffer, 
     int cch, 
     ref int pdwPriority, 
     SIZE prgSize, 
     int dwRecClrDepth, 
     ref int pdwFlags);

  [PreserveSig]
    Int32 Extract(out IntPtr phBmpThumbnail);
}

IShellFolder もインポートしましたが、簡潔にするためにここでは言及しません。私の意図は、シェルフォルダーを使用してファイルのサムネイルにアクセスすることです。サムネイルを取得するコードは次のとおりです。しかし、IExtractImage.GetLocation() への呼び出しが NullReference 例外で失敗し、

「タイプ 'System.NullReferenceException' の例外が CCDash.exe で発生しましたが、ユーザー コードで処理されませんでした。

追加情報: オブジェクト参照がオブジェクトのインスタンスに設定されていません。」

誰かが私が見逃しているものを特定するのを手伝ってもらえますか?

public Bitmap GetThumbNail(string mediaFileName)
{
  IShellFolder shellDesktop;
  SHGetDesktopFolder(out shellDesktop);

  IntPtr pidlRoot;
  uint attribute = 0;
  string mediaPath = "C:\\Users\\<user>\\Videos"; // I have hard-coded the path for now
  uint pchEaten = 0;
  // Get the pidl of the media folder
  shellDesktop.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, mediaPath, ref pchEaten, out pidlRoot, ref attribute);

  Guid mediaFolderGuid = new Guid("000214E6-0000-0000-C000-000000000046");
  shellDesktop.BindToObject(pidlRoot, IntPtr.Zero, mediaFolderGuid, out shellMediaFolder);


  IntPtr pidlMediaFolder;
  // Get the pidl of the media file
  shellMediaFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, mediaFileName, ref pchEaten, out pidlMediaFolder, ref attribute);

  Guid mediaFileImgGuid = new Guid("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1");      
  uint rfgRes = 0;
  IExtractImage extractImage;
  shellMediaFolder.GetUIObjectOf(IntPtr.Zero, 1, out pidlMediaFolder, mediaFileImgGuid, ref rfgRes, out extractImage);

  SIZE size = new SIZE
  {
    cx = 40,
    cy = 40
  };

  int flags = 0x40 | 0x40;
  StringBuilder location = new StringBuilder(260, 260);
  int priority = 0;
  int requestedColourDepth = 0x20;
  IntPtr hBmp = IntPtr.Zero;
  // Now get the image
  extractImage.GetLocation(out location, location.Capacity, ref priority, size, requestedColourDepth, ref flags);
  extractImage.Extract(out hBmp);

  Bitmap thumbnail = Image.FromHbitmap(hBmp);

  return thumbnail;
} 

編集:

以下のようにコードを修正しました。最初のバージョンと大差ありませんが、エラー処理が少し増え、ドキュメントと変数名が改善され、コードをよりよく理解できるようになりました。変更されたコードは次のとおりです。

public Bitmap GetThumbNail(string mediaFileName)
{
  Bitmap thumbnail = null;

  //Step 1: Use SHGetDesktopFolder to get the desktop folder.
  IShellFolder shellDesktop;
  SHGetDesktopFolder(out shellDesktop);

  if (shellDesktop != null)
  {
    IntPtr pidlMediaFolder;
    try
    {
      uint attribute = 0;
      string mediaPath = Path.GetDirectoryName(mediaFileName);
      uint pchEaten = 0;
      // Step 2: Using the desktop's IShellFolder, pass the file's parent folder path name into ParseDisplayName to get its PIDL.
      shellDesktop.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, mediaPath, ref pchEaten, out pidlMediaFolder, ref attribute);
    }
    catch (Exception)
    {
      Marshal.ReleaseComObject(shellDesktop);
      return null;
    }

    if (pidlMediaFolder != IntPtr.Zero)
    {
      Guid mediaFolderGuid = new Guid("000214E6-0000-0000-C000-000000000046");
      IShellFolder shellMediaFolder;
      // Step 3: Using the desktop's IShellFolder, pass the PIDL into the BindToObject method 
      // and get the IShellFolder interface of the file's parent folder.          
      try
      {
        shellDesktop.BindToObject(pidlMediaFolder, IntPtr.Zero, mediaFolderGuid, out shellMediaFolder);
      }
      catch (Exception)
      {
        Marshal.ReleaseComObject(shellDesktop);
        return null;
      }

      if (shellMediaFolder != null)
      {
        IntPtr pidlMediaFile;
        uint attribute = 0;
        uint pchEaten = 0;
        // Step 4: Using the parent folder's IShellFolder, pass the file name into ParseDisplayName to get its PIDL.            
        int ret = shellMediaFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, mediaFileName, ref pchEaten, out pidlMediaFile, ref attribute);

        Guid mediaFileImgGuid = new Guid("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1");
        uint rfgRes = 0;
        IExtractImage extractImage;
        // Step 5: Using the parent folder's IShellFolder, pass the file's PIDL 
        // into the GetUIObjectOf. method to get the IExtractImage interface.            
        ret = shellMediaFolder.GetUIObjectOf(IntPtr.Zero, 1, out pidlMediaFile, mediaFileImgGuid, ref rfgRes, out extractImage);

        SIZE size = new SIZE
        {
          cx = 40,
          cy = 40
        };

        uint flags = 0x0200;
        StringBuilder location = new StringBuilder(260, 260);
        int priority = 0;
        int requestedColourDepth = 0x20;
        IntPtr hBmp = IntPtr.Zero;
        // Now get the image
        extractImage.GetLocation(out location, location.Capacity, ref priority, size, requestedColourDepth, ref flags);
        extractImage.Extract(out hBmp);

        thumbnail = Image.FromHbitmap(hBmp);
      }
    }
  }
  return thumbnail;
}

ステップ 4 で、pidlMediaFile が正しく取得されず、その値が ParseDisplayName() 呼び出し後も 0 のままであることがわかります。ここから問題が始まります。ファイルの親フォルダーでは正常に取得されるのに、ファイル名の pidl が取得されない理由がわかりません。

4

1 に答える 1

0

からextractImage返されているようです。からの戻り値をチェックして、値が返される理由を確認してください。nullGetUIObjectOf()HRESULTGetUIObjectOf()null

編集:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa378137%28v=vs.85%29.aspxから:

E_INVALIDARG    One or more arguments are not valid 0x80070057

ドキュメントによると、3 番目の引数は[in]引数ではなく、[out]引数です。

于 2012-10-19T00:55:18.047 に答える