asp.net SHGetFileInfo [winapi call]

时间:2010-10-20 10:04:57

标签: asp.net winapi

我的asp.net网站需要树文件。 为了获取图标,我尝试使用SHGetFileInfo api函数。 在非asp.net应用程序,它运行良好,返回更正图标。当我在asp.net上下文时,我得到了:

尝试读取或写入受保护的内存。

怎么了?我可以在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);
    }
} 

1 个答案:

答案 0 :(得分:1)

您用于SHGetFileInfo的P / Invoke签名是错误的 - 请使用at PInvoke.net

SHGetFileInfo返回在访问返回的数据之前需要检查成功的值。如果API调用失败,则访问您期望的Icon的结果是不可预测的(通常是不好的)。

一旦你知道错误是什么,你就可以把它作为一个单独的问题来解决。从托管代码P / Invoke 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
    }