2010-10-20 20 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 
    }