code

C # Windows API를 통해 파일에서 축소판 가져 오기

codestyles 2020. 11. 5. 08:03
반응형

C # Windows API를 통해 파일에서 축소판 가져 오기


Windows 탐색기에는 파일의 축소판을 표시하는 기능이 있습니다. 이러한 축소판은 핵심 및 타사 셸 확장에서 제공됩니다.

셸을 확장하여 Windows에 썸네일을 제공하는 방법을 알고 있습니다.

내가 원하는 것은 C #을 사용하여 셸을 통해 시스템의 모든 파일에서 축소판 이미지를 검색하는 것입니다. 이것이 가능한가?

기본적으로 저는 사용자 지정 파일 브라우저를 작성 중이며 축소판을 표시하고 싶습니다. 지구상의 모든 파일을 구문 분석하여 고유의 축소판을 만들 수는 없습니다.

설명 : 많은 답변이 웹 페이지 축소판 또는 이미지 크기 조정을 중심으로하는 것 같습니다. 그러나 그것은 내가 찾고있는 것이 아닙니다. 내가 원하는 것은 Windows에 .DOC, .PDF, .3DM, .DWG 등의 썸네일 표현을 요청하는 것입니다. Windows는 이미 방법을 알고 있기 때문에 직접 구문 분석, 렌더링 및 축소판을 만들고 싶지 않습니다.

답변으로 게시 한 코드는 실제로 작동합니다 ... 어쩌면 단순화하고 약간 정리할 수 있습니다.


오늘 이것을 살펴 보았습니다. 몇 달이 지났지 만 저를 위해 작업을 완료했습니다 (Win7에서 MPEG-4 파일의 썸네일 추출).

암호:

ShellFile shellFile = ShellFile.FromFilePath(pathToYourFile);
Bitmap shellThumb = shellFile.Thumbnail.ExtraLargeBitmap;

도움이 되었기를 바랍니다.


SharePoint의 마이크로 소프트 오피스 썸네일 에서 http://msdn.microsoft.com/en-us/library/aa289172(VS.71).aspx . 정확히 당신이 원하는 것입니다. ( http://www.developerfusion.com/tools/convert/vb-to-csharp/ 사용하여 VB.NET 코드를 C #으로 변환하는 데 문제가 없었습니다.)

답변에 게시 한 코드와 관련하여 http://www.vbaccelerator.com/home/net/code/libraries/Shell_Projects/Thumbnail_Extraction/article.asp 의 Shell사용한 Thumbnail Extraction 은 코드의 원본 기사입니다. 나는 거의 모든 것을 믿는다IExtractImage샘플 (검색 할 수 있음)은 원본에서 가져온 이름 지정 규칙, 주석 등으로 ​​인해이 기사의 코드를 기반으로합니다. 이 기사는 2003 년 4 월에 작성되었으므로 일부 비표준 (비 .NET) 코딩 규칙을 따릅니다. 몇 가지 기본 테스트를 수행했으며 가비지 수집 문제, 관리되지 않는 리소스 문제 해제 및 기타 정리 문제가 있습니다. 따라서 해당 기사의 코드를 피할 것을 강력히 권장합니다. 또한 코드가 구조화되어 유지 관리가 어렵습니다.

MSDN에는 2005 년 7 월자인 SharePoint의 Microsoft Office Thumbnails ( http://msdn.microsoft.com/en-us/library/aa289172 (VS.71) .aspx) 라는 깔끔한 단순한 버전이 있습니다 . 이 코드와 기사의 코드는 유사점을 공유 하므로 셸을 사용한 축소판 추출 기사가 SharePoint 기사 의 기초 라고 믿게 됩니다. 의 VB.NET 버전은 매개 변수 GetThumbnailImage무시 longestEdge하지만 C ++ 버전은 매개 변수를 사용하고 ORIGSIZEQUALITY플래그 의 사용을 문서화합니다 . 또한이 코드 FreeCoTaskMem는 셸 IMalloc.NET 대신 .NET을 사용하는 방법을 보여줍니다 SHGetMalloc.

IExtractImage파일, 폴더 및 기타 네임 스페이스 개체와 함께 작동합니다. MSDN 코드는 숨겨진 파일과 함께 작동하지만 vbAccelerator 코드 SHCONTF_INCLUDEHIDDENEnumObjects호출에 추가되어야합니다 . 또한 vbAccelerator는 지정된 파일을 찾는 셸 폴더의 개체를 열거하므로 시간 낭비로 보입니다. GetUIObjectOf호출에 사용되는 올바른 "상대"PIDL을 찾는 데 필요할 수 있습니다 .


ShellThumbnail (Work-In-Progress)

http://cid-7178d2c79ba0a7e3.office.live.com/self.aspx/.Public/ShellThumbnail.zip 에서 샘플 프로젝트를 완료 하십시오 .

Imports System.Runtime.InteropServices

Namespace Shell

    ''' <summary>
    ''' Generates a thumbnail of a folder's picture or a file's image.
    ''' </summary>
    ''' <remarks>This is the "Folder's Picture" and not the "Folder's Icon"! Use SHGetFileInfo to generate the thumbnail for a folder's icon or for a file that does not have a thumbnail handler.</remarks>
    ''' <reference>Microsoft Office Thumbnails in SharePoint at http://msdn.microsoft.com/en-us/library/aa289172%28VS.71%29.aspx.</reference>
    Public Class ShellThumbnail

        'TODO - Work out the details for image size and IEIFLAG handling.

#Region " Determining Thumbnail Size and Quality [documentation] "

        'http://support.microsoft.com/kb/835823
        'Determining Thumbnail Size and Quality
        'Browse to HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer. Create or modify two DWORDs called ThumbnailSize and ThumbnailQuality. For ThumbnailSize set the value in pixels, with the default being 96. For ThumbnailQuality set the value as a number that represents the percentage quality between 50 and 100.


        'http://www.pctools.com/guides/registry/detail/1066/ (modified)
        '  User Key: [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer]
        'System Key: [HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer]
        'Value Name: ThumbnailSize, ThumbnailQuality
        ' Data Type: REG_DWORD (DWORD Value)
        'Value Data: Size in pixels (32-255), Quality Percentage (50-100)


        'Microsoft® Windows® XP Registry Guide 
        'Jerry Honeycutt 
        '09/11/2002 
        'Microsoft Press
        'http://www.microsoft.com/mspress/books/sampchap/6232.aspx#118
        '<H3><I><A name=118></A>Thumbnails</I></H3>The Thumbnails category controls the 
        'quality of thumbnails in Windows Explorer. Table 5-10 describes the values for 
        'Image Quality and Size. Create values that you don't see in the registry. The 
        'default value for <CODE>ThumbnailQuality</CODE> is <CODE>0x5A</CODE>. The 
        'default value for <CODE>ThumbnailSize</CODE> is <CODE>0x60</CODE>. Keep in mind 
        'that higher quality and larger thumbnails require more disk space, which is not 
        'usually a problem, but they also take longer to display. Changing the quality 
        'does not affect thumbnails that already exist on the file system.
        '<P><B>Table 5-10 </B><I>Values in Thumbnails</I>
        '<P>
        '<TABLE border=0 cellSpacing=1 cellPadding=4 width="100%">
        '<TBODY>
        '<TR>
        '<TD bgColor=#999999 vAlign=top><B>Setting</B></TD>
        '<TD bgColor=#999999 vAlign=top><B>Name</B></TD>
        '<TD bgColor=#999999 vAlign=top><B>Type</B></TD>
        '<TD bgColor=#999999 vAlign=top><B>Data</B></TD></TR>
        '<TR>
        '<TD bgColor=#cccccc 
        'vAlign=top><CODE><B>HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer</B></CODE></TD>
        '<TD bgColor=#cccccc vAlign=top> </TD>
        '<TD bgColor=#cccccc vAlign=top> </TD>
        '<TD bgColor=#cccccc vAlign=top> </TD></TR>
        '<TR>
        '<TD bgColor=#cccccc vAlign=top><CODE>Image Quality</CODE></TD>
        '<TD bgColor=#cccccc vAlign=top><CODE>ThumbnailQuality</CODE></TD>
        '<TD bgColor=#cccccc vAlign=top><CODE>REG_DWORD</CODE></TD>
        '<TD bgColor=#cccccc vAlign=top><CODE>0x32 - 0x64</CODE></TD></TR>
        '<TR>
        '<TD bgColor=#cccccc vAlign=top><CODE>Size (pixels)</CODE></TD>
        '<TD bgColor=#cccccc vAlign=top><CODE>ThumbnailSize</CODE></TD>
        '<TD bgColor=#cccccc vAlign=top><CODE>REG_DWORD</CODE></TD>
        '<TD bgColor=#cccccc vAlign=top><CODE>0x20 - 0xFF</CODE></TD></TR></TBODY></TABLE></P>

#End Region

        Public Shared ReadOnly DefaultThumbnailSize As New System.Drawing.Size(96, 96)

        Public Const DefaultColorDepth As Integer = 32

        ''' <summary>
        ''' Used to request an image from an object, such as an item in a Shell folder.
        ''' </summary>
        ''' <param name="path">An absolute path to a file or folder.</param>
        Public Shared Function ExtractImage(ByVal path As String) As Bitmap
            Return ExtractImage(path, System.Drawing.Size.Empty, DefaultColorDepth, 0)
        End Function

        ''' <summary>
        ''' Used to request an image from an object, such as an item in a Shell folder.
        ''' </summary>
        ''' <param name="path">An absolute path to a file or folder.</param>
        ''' <param name="size"></param>
        Public Shared Function ExtractImage(ByVal path As String, ByVal size As System.Drawing.Size) As Bitmap
            Return ExtractImage(path, size, DefaultColorDepth, 0)
        End Function

        ''' <summary>
        ''' Used to request an image from an object, such as an item in a Shell folder.
        ''' </summary>
        ''' <param name="path">An absolute path to a file or folder.</param>
        ''' <param name="size"></param>
        ''' <param name="recommendedColorDepth">The recommended color depth in units of bits per pixel. The default is 32.</param>
        Public Shared Function ExtractImage(ByVal path As String, ByVal size As System.Drawing.Size, ByVal recommendedColorDepth As Integer) As Bitmap
            Return ExtractImage(path, size, recommendedColorDepth, 0)
        End Function

        ''' <summary>
        ''' Used to request an image from an object, such as an item in a Shell folder.
        ''' </summary>
        ''' <param name="path">An absolute path to a file or folder.</param>
        ''' <param name="size"></param>
        ''' <param name="recommendedColorDepth">The recommended color depth in units of bits per pixel. The default is 32.</param>
        Private Shared Function ExtractImage(ByVal path As String, ByVal size As System.Drawing.Size, ByVal recommendedColorDepth As Integer, ByVal flags As IEIFLAG) As Bitmap
            Dim oResult As Bitmap = Nothing

            Dim oDesktopFolder As IShellFolder = Nothing
            Dim hParentIDL As IntPtr
            Dim hIDL As IntPtr

            Dim oParentFolder As IShellFolder
            Dim hParentFolder As IntPtr
            Dim oExtractImage As IExtractImage
            Dim hExtractImage As IntPtr

            'Divide the file name into a path and file/folder name.
            Dim sFolderName As String = System.IO.Path.GetDirectoryName(path)
            Dim sBaseName As String = System.IO.Path.GetFileName(path)

            'Get the desktop IShellFolder.
            If SHGetDesktopFolder(oDesktopFolder) <> Missico.Win32.S_OK Then
                Throw New System.Runtime.InteropServices.COMException
            End If

            'Get the parent folder for the specified path.
            oDesktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, sFolderName, 0, hParentIDL, 0)
            oDesktopFolder.BindToObject(hParentIDL, IntPtr.Zero, ShellGUIDs.IID_IShellFolder, hParentFolder)
            oParentFolder = CType(Marshal.GetTypedObjectForIUnknown(hParentFolder, GetType(IShellFolder)), IShellFolder)

            'Get the file/folder's IExtractImage
            oParentFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, sBaseName, 0, hIDL, 0)
            oParentFolder.GetUIObjectOf(IntPtr.Zero, 1, New IntPtr() {hIDL}, ShellGUIDs.IID_IExtractImage, IntPtr.Zero, hExtractImage)

            'Free the pidls. The Runtime Callable Wrappers (RCW) should automatically release the COM objects.
            Marshal.FreeCoTaskMem(hParentIDL)
            Marshal.FreeCoTaskMem(hIDL)

            Marshal.FinalReleaseComObject(oParentFolder)
            Marshal.FinalReleaseComObject(oDesktopFolder)

            If hExtractImage = IntPtr.Zero Then

                'There is no handler for this file, which is odd. I believe we should default the file's type icon.
                Debug.WriteLine(String.Format("There is no thumbnail for the specified file '{0}'.", path), "ShellThumbnail.ExtractImage")

            Else

                oExtractImage = CType(Marshal.GetTypedObjectForIUnknown(hExtractImage, GetType(IExtractImage)), IExtractImage)

                'Set the size and flags
                Dim oSize As Missico.Win32.SIZE 'must specify a size
                Dim iFlags As IEIFLAG = flags Or IEIFLAG.IEIFLAG_ORIGSIZE Or IEIFLAG.IEIFLAG_QUALITY Or IEIFLAG.IEIFLAG_ASPECT

                If size.IsEmpty Then

                    oSize.cx = DefaultThumbnailSize.Width
                    oSize.cy = DefaultThumbnailSize.Height

                Else

                    oSize.cx = size.Width
                    oSize.cy = size.Height

                End If


                Dim hBitmap As IntPtr
                Dim sPath As New System.Text.StringBuilder(Missico.Win32.MAX_PATH, Missico.Win32.MAX_PATH)


                oExtractImage.GetLocation(sPath, sPath.Capacity, 0, oSize, recommendedColorDepth, iFlags)

                'if the specified path is to a folder then IExtractImage.Extract fails.

                Try

                    oExtractImage.Extract(hBitmap)

                Catch ex As System.Runtime.InteropServices.COMException

                    'clear the handle since extract failed
                    hBitmap = IntPtr.Zero

                    Debug.WriteLine(String.Format("There is no thumbnail for the specified folder '{0}'.", path), "ShellThumbnail.ExtractImage")

                Finally

                    Marshal.FinalReleaseComObject(oExtractImage)

                End Try

                If Not hBitmap.Equals(IntPtr.Zero) Then

                    'create the image from the handle
                    oResult = System.Drawing.Bitmap.FromHbitmap(hBitmap)

                    'dump the properties to determine what kind of bitmap is returned
                    'Missico.Diagnostics.ObjectDumper.Write(oResult)

                    'Tag={ }
                    'PhysicalDimension={Width=96, Height=96}
                    'Size={Width=96, Height=96}
                    'Width=96
                    'Height=96
                    'HorizontalResolution=96
                    'VerticalResolution=96
                    'Flags=335888
                    'RawFormat={ }
                    'PixelFormat=Format32bppRgb
                    'Palette={ }
                    'FrameDimensionsList=...
                    'PropertyIdList=...
                    'PropertyItems=...

                    Missico.Win32.DeleteObject(hBitmap) 'release the handle

                End If

            End If

            Return oResult
        End Function

    End Class

End Namespace

도움이 될 수 있습니다.

http://blogs.msdn.com/windowssdk/archive/2009/06/12/windows-api-code-pack-for-microsoft-net-framework.aspx

여기에는 Shell API가 포함되며 셸이 할 수있는 거의 모든 작업을 수행 할 수 있습니다 (렌더링 축소판 포함).


다음은 인터넷에서 검색 한 수업입니다. 원본 코드는 http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21789724.html 에서 가져온 것처럼 보이지만 적절한 속성을 제공하는 것으로 보이지 않습니다. 여기에서 소스를 찾았습니다. http://www.vbforums.com/showthread.php?t=527704

다음은 적절한 COM 호출이 포함 된 클래스입니다.


using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace RMA.Shell
{
  public class ShellThumbnail : IDisposable
  {

    [Flags]
    private enum ESTRRET
    {
      STRRET_WSTR = 0,
      STRRET_OFFSET = 1,
      STRRET_CSTR = 2
    }

    [Flags]
    private enum ESHCONTF
    {
      SHCONTF_FOLDERS = 32,
      SHCONTF_NONFOLDERS = 64,
      SHCONTF_INCLUDEHIDDEN = 128,
    }

    [Flags]
    private enum ESHGDN
    {
      SHGDN_NORMAL = 0,
      SHGDN_INFOLDER = 1,
      SHGDN_FORADDRESSBAR = 16384,
      SHGDN_FORPARSING = 32768
    }

    [Flags]
    private enum ESFGAO
    {
      SFGAO_CANCOPY = 1,
      SFGAO_CANMOVE = 2,
      SFGAO_CANLINK = 4,
      SFGAO_CANRENAME = 16,
      SFGAO_CANDELETE = 32,
      SFGAO_HASPROPSHEET = 64,
      SFGAO_DROPTARGET = 256,
      SFGAO_CAPABILITYMASK = 375,
      SFGAO_LINK = 65536,
      SFGAO_SHARE = 131072,
      SFGAO_READONLY = 262144,
      SFGAO_GHOSTED = 524288,
      SFGAO_DISPLAYATTRMASK = 983040,
      SFGAO_FILESYSANCESTOR = 268435456,
      SFGAO_FOLDER = 536870912,
      SFGAO_FILESYSTEM = 1073741824,
      SFGAO_HASSUBFOLDER = -2147483648,
      SFGAO_CONTENTSMASK = -2147483648,
      SFGAO_VALIDATE = 16777216,
      SFGAO_REMOVABLE = 33554432,
      SFGAO_COMPRESSED = 67108864,
    }

    private enum EIEIFLAG
    {
      IEIFLAG_ASYNC = 1,
      IEIFLAG_CACHE = 2,
      IEIFLAG_ASPECT = 4,
      IEIFLAG_OFFLINE = 8,
      IEIFLAG_GLEAM = 16,
      IEIFLAG_SCREEN = 32,
      IEIFLAG_ORIGSIZE = 64,
      IEIFLAG_NOSTAMP = 128,
      IEIFLAG_NOBORDER = 256,
      IEIFLAG_QUALITY = 512
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0, CharSet = CharSet.Auto)]
    private struct STRRET_CSTR
    {
      public ESTRRET uType;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 520)]
      public byte[] cStr;
    }

    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
    private struct STRRET_ANY
    {
      [FieldOffset(0)]
      public ESTRRET uType;
      [FieldOffset(4)]
      public IntPtr pOLEString;
    }
    [StructLayoutAttribute(LayoutKind.Sequential)]
    private struct SIZE
    {
      public int cx;
      public int cy;
    }

    [ComImport(), Guid("00000000-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IUnknown
    {

      [PreserveSig()]
      IntPtr QueryInterface(ref Guid riid, ref IntPtr pVoid);

      [PreserveSig()]
      IntPtr AddRef();

      [PreserveSig()]
      IntPtr Release();
    }

    [ComImportAttribute()]
    [GuidAttribute("00000002-0000-0000-C000-000000000046")]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IMalloc
    {

      [PreserveSig()]
      IntPtr Alloc(int cb);

      [PreserveSig()]
      IntPtr Realloc(IntPtr pv, int cb);

      [PreserveSig()]
      void Free(IntPtr pv);

      [PreserveSig()]
      int GetSize(IntPtr pv);

      [PreserveSig()]
      int DidAlloc(IntPtr pv);

      [PreserveSig()]
      void HeapMinimize();
    }

    [ComImportAttribute()]
    [GuidAttribute("000214F2-0000-0000-C000-000000000046")]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IEnumIDList
    {

      [PreserveSig()]
      int Next(int celt, ref IntPtr rgelt, ref int pceltFetched);

      void Skip(int celt);

      void Reset();

      void Clone(ref IEnumIDList ppenum);
    }

    [ComImportAttribute()]
    [GuidAttribute("000214E6-0000-0000-C000-000000000046")]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IShellFolder
    {

      void ParseDisplayName(IntPtr hwndOwner, IntPtr pbcReserved,
        [MarshalAs(UnmanagedType.LPWStr)]string lpszDisplayName,
        ref int pchEaten, ref IntPtr ppidl, ref int pdwAttributes);

      void EnumObjects(IntPtr hwndOwner,
        [MarshalAs(UnmanagedType.U4)]ESHCONTF grfFlags,
        ref IEnumIDList ppenumIDList);

      void BindToObject(IntPtr pidl, IntPtr pbcReserved, ref Guid riid,
        ref IShellFolder ppvOut);

      void BindToStorage(IntPtr pidl, IntPtr pbcReserved, ref Guid riid, IntPtr ppvObj);

      [PreserveSig()]
      int CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);

      void CreateViewObject(IntPtr hwndOwner, ref Guid riid,
        IntPtr ppvOut);

      void GetAttributesOf(int cidl, IntPtr apidl,
        [MarshalAs(UnmanagedType.U4)]ref ESFGAO rgfInOut);

      void GetUIObjectOf(IntPtr hwndOwner, int cidl, ref IntPtr apidl, ref Guid riid, ref int prgfInOut, ref IUnknown ppvOut);

      void GetDisplayNameOf(IntPtr pidl,
        [MarshalAs(UnmanagedType.U4)]ESHGDN uFlags,
        ref STRRET_CSTR lpName);

      void SetNameOf(IntPtr hwndOwner, IntPtr pidl,
        [MarshalAs(UnmanagedType.LPWStr)]string lpszName,
        [MarshalAs(UnmanagedType.U4)] ESHCONTF uFlags,
        ref IntPtr ppidlOut);
    }
    [ComImportAttribute(), GuidAttribute("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IExtractImage
    {
      void GetLocation([Out(), MarshalAs(UnmanagedType.LPWStr)]
        StringBuilder pszPathBuffer, int cch, ref int pdwPriority, ref SIZE prgSize, int dwRecClrDepth, ref int pdwFlags);

      void Extract(ref IntPtr phBmpThumbnail);
    }

    private class UnmanagedMethods
    {

      [DllImport("shell32", CharSet = CharSet.Auto)]
      internal extern static int SHGetMalloc(ref IMalloc ppMalloc);

      [DllImport("shell32", CharSet = CharSet.Auto)]
      internal extern static int SHGetDesktopFolder(ref IShellFolder ppshf);

      [DllImport("shell32", CharSet = CharSet.Auto)]
      internal extern static int SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath);

      [DllImport("gdi32", CharSet = CharSet.Auto)]
      internal extern static int DeleteObject(IntPtr hObject);

    }

    ~ShellThumbnail()
    {
      Dispose();
    }

    private IMalloc alloc = null;
    private bool disposed = false;
    private Size _desiredSize = new Size(100, 100);
    private Bitmap _thumbNail;

    public Bitmap ThumbNail
    {
      get
      {
        return _thumbNail;
      }
    }

    public Size DesiredSize
    {
      get { return _desiredSize; }
      set { _desiredSize = value; }
    }
    private IMalloc Allocator
    {
      get
      {
        if (!disposed)
        {
          if (alloc == null)
          {
            UnmanagedMethods.SHGetMalloc(ref alloc);
          }
        }
        else
        {
          Debug.Assert(false, "Object has been disposed.");
        }
        return alloc;
      }
    }

    public Bitmap GetThumbnail(string fileName)
    {
      if (string.IsNullOrEmpty(fileName))
        return null;

      if (!File.Exists(fileName) && !Directory.Exists(fileName))
      {
        throw new FileNotFoundException(string.Format("The file '{0}' does not exist", fileName), fileName);
      }
      if (_thumbNail != null)
      {
        _thumbNail.Dispose();
        _thumbNail = null;
      }
      IShellFolder folder = null;
      try
      {
        folder = getDesktopFolder;
      }
      catch (Exception ex)
      {
        throw ex;
      }
      if (folder != null)
      {
        IntPtr pidlMain = IntPtr.Zero;
        try
        {
          int cParsed = 0;
          int pdwAttrib = 0;
          string filePath = Path.GetDirectoryName(fileName);
          folder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, filePath, ref cParsed, ref pidlMain, ref pdwAttrib);
        }
        catch (Exception ex)
        {
          Marshal.ReleaseComObject(folder);
          throw ex;
        }
        if (pidlMain != IntPtr.Zero)
        {
          Guid iidShellFolder = new Guid("000214E6-0000-0000-C000-000000000046");
          IShellFolder item = null;
          try
          {
            folder.BindToObject(pidlMain, IntPtr.Zero, ref iidShellFolder, ref item);
          }
          catch (Exception ex)
          {
            Marshal.ReleaseComObject(folder);
            Allocator.Free(pidlMain);
            throw ex;
          }
          if (item != null)
          {
            IEnumIDList idEnum = null;
            try
            {
              item.EnumObjects(IntPtr.Zero, (ESHCONTF.SHCONTF_FOLDERS | ESHCONTF.SHCONTF_NONFOLDERS), ref idEnum);
            }
            catch (Exception ex)
            {
              Marshal.ReleaseComObject(folder);
              Allocator.Free(pidlMain);
              throw ex;
            }
            if (idEnum != null)
            {
              int hRes = 0;
              IntPtr pidl = IntPtr.Zero;
              int fetched = 0;
              bool complete = false;
              while (!complete)
              {
                hRes = idEnum.Next(1, ref pidl, ref fetched);
                if (hRes != 0)
                {
                  pidl = IntPtr.Zero;
                  complete = true;
                }
                else
                {
                  if (_getThumbNail(fileName, pidl, item))
                  {
                    complete = true;
                  }
                }
                if (pidl != IntPtr.Zero)
                {
                  Allocator.Free(pidl);
                }
              }
              Marshal.ReleaseComObject(idEnum);
            }
            Marshal.ReleaseComObject(item);
          }
          Allocator.Free(pidlMain);
        }
        Marshal.ReleaseComObject(folder);
      }
      return ThumbNail;
    }

    private bool _getThumbNail(string file, IntPtr pidl, IShellFolder item)
    {
      IntPtr hBmp = IntPtr.Zero;
      IExtractImage extractImage = null;
      try
      {
        string pidlPath = PathFromPidl(pidl);
        if (Path.GetFileName(pidlPath).ToUpper().Equals(Path.GetFileName(file).ToUpper()))
        {
          IUnknown iunk = null;
          int prgf = 0;
          Guid iidExtractImage = new Guid("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1");
          item.GetUIObjectOf(IntPtr.Zero, 1, ref pidl, ref iidExtractImage, ref prgf, ref iunk);
          extractImage = (IExtractImage)iunk;
          if (extractImage != null)
          {
            Console.WriteLine("Got an IExtractImage object!");
            SIZE sz = new SIZE();
            sz.cx = DesiredSize.Width;
            sz.cy = DesiredSize.Height;
            StringBuilder location = new StringBuilder(260, 260);
            int priority = 0;
            int requestedColourDepth = 32;
            EIEIFLAG flags = EIEIFLAG.IEIFLAG_ASPECT | EIEIFLAG.IEIFLAG_SCREEN;
            int uFlags = (int)flags;
            try
            {
              extractImage.GetLocation(location, location.Capacity, ref priority, ref sz, requestedColourDepth, ref uFlags);
              extractImage.Extract(ref hBmp);
            }
            catch (System.Runtime.InteropServices.COMException ex)
            {

            }
            if (hBmp != IntPtr.Zero)
            {
              _thumbNail = Bitmap.FromHbitmap(hBmp);
            }
            Marshal.ReleaseComObject(extractImage);
            extractImage = null;
          }
          return true;
        }
        else
        {
          return false;
        }
      }
      catch (Exception ex)
      {
        if (hBmp != IntPtr.Zero)
        {
          UnmanagedMethods.DeleteObject(hBmp);
        }
        if (extractImage != null)
        {
          Marshal.ReleaseComObject(extractImage);
        }
        throw ex;
      }
    }

    private string PathFromPidl(IntPtr pidl)
    {
      StringBuilder path = new StringBuilder(260, 260);
      int result = UnmanagedMethods.SHGetPathFromIDList(pidl, path);
      if (result == 0)
      {
        return string.Empty;
      }
      else
      {
        return path.ToString();
      }
    }

    private IShellFolder getDesktopFolder
    {
      get
      {
        IShellFolder ppshf = null;
        int r = UnmanagedMethods.SHGetDesktopFolder(ref ppshf);
        return ppshf;
      }
    }

    public void Dispose()
    {
      if (!disposed)
      {
        if (alloc != null)
        {
          Marshal.ReleaseComObject(alloc);
        }
        alloc = null;
        if (_thumbNail != null)
        {
          _thumbNail.Dispose();
        }
        disposed = true;
      }
    }
  }
}

Windows API 코드 팩 썸네일 호출은 안타깝게도 XP / 2003에서 지원되지 않습니다.


정확히 당신이 요청한 것은 아니지만 다음은 Thumbs.db 파일을 여는 프로젝트 입니다.
Wikipedia 기사에는 Vista 및 7에서 썸네일을 찾을 수있는 위치에 대한 자세한 정보가 있습니다 .

이미지를 가져 오는 코드는 다음과 같습니다.

public byte[] GetThumbData(string filename)
{
    IStorageWrapper wrapper = new IStorageWrapper(_thumbDBFile, false);
    foreach(CatalogItem catItem in _catalogItems)
    {
        if (catItem.filename == filename)
        {
            string streamName = BuildReverseString(catItem.itemID);
            FileObject fileObject = wrapper.OpenUCOMStream(null, streamName);
            byte[] rawJPGData = new byte [fileObject.Length];
            fileObject.Read(rawJPGData, 0, (int)fileObject.Length);
            fileObject.Close();

            // 3 ints of header data need to be removed
            // Don't know what first int is.
            // 2nd int is thumb index
            // 3rd is size of thumbnail data.
            byte[] jpgData = new byte[rawJPGData.Length - 12];
            for (int index = 12; index < jpgData.Length; index++)
            {
                jpgData[index - 12] = rawJPGData[index];
            }
            return jpgData;
        }
    }
    return null;
}

public Image GetThumbnailImage(string filename)
{
    byte[] thumbData = GetThumbData(filename);
    if (null == thumbData)
    {
        return null;
    }
    MemoryStream ms = new MemoryStream(thumbData);
    Image img = Image.FromStream(ms);
    return img;
}

You should use the windows GDI+ to get these thumbnails, like this.

참고URL : https://stackoverflow.com/questions/1439719/c-sharp-get-thumbnail-from-file-via-windows-api

반응형