2010-10-20 56 views
0

我需要在我的asp.net網站的樹文件。 爲了獲取圖標,我嘗試使用SHGetFileInfo api函數。 在非asp.net應用程序中運行良好,返回更正圖標。當我在asp.net環境中使用它時,我得到了:asp.net SHGetFileInfo [winapi調用]

試圖讀取或寫入受保護的內存。

怎麼了?我可以在asp.net上下文中獲取Fiel圖標嗎?

代碼:

public class ExtractIcon 
{ 
    [DllImport("Shell32.dll")] 
    private static extern int SHGetFileInfo(
    string pszPath, 
    uint dwFileAttributes, 
    out SHFILEINFO psfi, 
    uint cbfileInfo, 
    uint uFlags 
    ); 

    [StructLayout(LayoutKind.Sequential)] 
    private struct SHFILEINFO 
    { 
     public SHFILEINFO(bool b) 
     { 
      hIcon = IntPtr.Zero; 
      iIcon = 0; 
      dwAttributes = 0; 
      szDisplayName = String.Empty; 
      szTypeName = String.Empty; 
     } 

     public IntPtr hIcon; 
     public int iIcon; 
     public uint dwAttributes; 

     [MarshalAs(UnmanagedType.LPStr, SizeConst = 260)] 
     public string szDisplayName; 

     [MarshalAs(UnmanagedType.LPStr, SizeConst = 80)] 
     public string szTypeName; 
    }; 

    public const uint SHGFI_ICON = 0x000000100; // get icon 
    public const uint SHGFI_DISPLAYNAME = 0x000000200; // get display name 
    public const uint SHGFI_TYPENAME = 0x000000400; // get type name 
    public const uint SHGFI_ATTRIBUTES = 0x000000800; // get attributes 
    public const uint SHGFI_ICONLOCATION = 0x000001000; // get icon location 
    public const uint SHGFI_EXETYPE = 0x000002000; // return exe type 
    public const uint SHGFI_SYSICONINDEX = 0x000004000; // get system icon index 
    public const uint SHGFI_LINKOVERLAY = 0x000008000; // put a link overlay on icon 
    public const uint SHGFI_SELECTED = 0x000010000; // show icon in selected state 
    public const uint SHGFI_ATTR_SPECIFIED = 0x000020000; // get only specified attributes 
    public const uint SHGFI_LARGEICON = 0x000000000; // get large icon 
    public const uint SHGFI_SMALLICON = 0x000000001; // get small icon 
    public const uint SHGFI_OPENICON = 0x000000002; // get open icon 
    public const uint SHGFI_SHELLICONSIZE = 0x000000004; // get shell size icon 
    public const uint SHGFI_PIDL = 0x000000008; // pszPath is a pidl 
    public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010; // use passed dwFileAttribute 
    public const uint SHGFI_ADDOVERLAYS = 0x000000020; 
    public const uint SHGFI_OVERLAYINDEX = 0x000000040; 

    private static Icon GetIcon(string strPath, uint flags) 
    { 
     SHFILEINFO info = new SHFILEINFO(true); 
     int cbFileInfo = Marshal.SizeOf(info); 

     SHGetFileInfo(strPath, 256, out info, (uint)cbFileInfo, flags); 
     return Icon.FromHandle(info.hIcon); 
    } 

    /// <summary> 
    /// Get the associated Icon for a file or application, this method always returns 
    /// an icon. If the strPath is invalid or there is no idonc the default icon is returned 
    /// </summary> 
    /// <param name="strPath">full path to the file</param> 
    /// <param name="bSmall">if true, the 16x16 icon is returned otherwise the 32x32</param> 
    /// <returns></returns> 
    public static Icon GetIcon(string strPath, bool bSmall) 
    { 
     uint flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES; 
     flags |= bSmall ? SHGFI_SMALLICON : SHGFI_LARGEICON; 
     return GetIcon(strPath, flags); 
    } 

    public static Icon GetIcon(string strPath, bool bSmall, bool bOpened) 
    { 
     uint flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES; 
     flags |= bSmall ? SHGFI_SMALLICON : SHGFI_LARGEICON; 
     flags |= bOpened ? SHGFI_OPENICON : 0; 
     return GetIcon(strPath, flags); 
    } 
} 
+0

你介意來發表您的問題的代碼? – Vantomex 2010-10-20 13:33:41

+0

如果您也可以發佈SHGetFileInfo()聲明對我們很有用。 – Vantomex 2010-10-20 13:58:58

+0

您正在運行的是什麼ASP.NET和計算機體系結構,32位或64位?因爲'SHGetFileInfo()'的返回值是'DWORD_PTR',而不是'int'。 DWORD_PTR類型是一種特殊類型,它是32位體系結構中的DWORD,它是64位體系結構中的DWORD64。 – Vantomex 2010-10-21 09:03:56

回答

1

的的P/Invoke您正在使用SHGetFileInfo簽名是錯誤的 - 使用一個at PInvoke.net

SHGetFileInfo返回一個值,您在訪問返回的數據之前需要檢查成功。如果API調用失敗,訪問您所期望的圖標的結果是不可預知的(通常很糟糕)。

一旦您知道錯誤是什麼,您可以將其作爲一個單獨的問題解決。當從託管代碼中調用/調用Win32 API時,您絕對不應該忽略錯誤檢查代碼。請閱讀MSDN docs以瞭解成功的具體內容以及期望的錯誤。

你的情況:

SHGetFileInfo(strPath, 256, out info, (uint)cbFileInfo, flags); 
    return Icon.FromHandle(info.hIcon); 

應該是這樣的

IntPtr result = SHGetFileInfo(strPath, 256, out info, (uint)cbFileInfo, flags); 
    if (result != IntPtr.Zero) 
    { 
     return Icon.FromHandle(info.hIcon); 
    } 
    else 
    { 
     // add error handling here 
    }