1

We have a tree view in a windows forms app that shows files using the appropriate file icon using the following code. My problem is that call to GetIcon() appears to corrupt my memory as I start getting various program crashes that I can't catch with a debugger after this call.
The program work when I change managedType.LPTStr to managedType.ByValTStr. Is this a true fix or just masking the problem?

This code appeared to be working in our last product release and I can't see anything that has changed. Using .NET 4.0. I only see the issue in Release mode.

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

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

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

                        [MarshalAs(UnmanagedType.LPTStr, SizeConst = 260)]//works if .ByValTStr is used instead
                        public string szDisplayName;
                        [MarshalAs(UnmanagedType.LPTStr, SizeConst = 80)]//works if .ByValTStr is used instead
                        public string szTypeName;
        };

 public static Icon GetIcon(string strPath, bool bSmall)
        {
            SHFILEINFO info = new SHFILEINFO(true);
            int cbFileInfo = Marshal.SizeOf(info);
            SHGFI flags;
            if (bSmall)
                flags = SHGFI.Icon|SHGFI.SmallIcon|SHGFI.UseFileAttributes;
            else
                flags = SHGFI.Icon|SHGFI.LargeIcon|SHGFI.UseFileAttributes;

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

2 に答える 2

0

まあ、それLPStrは構造体では適切ではないので、それを1つとしてマーシャリングして、機能することを期待することはできません。

typedef struct _SHFILEINFO {
  HICON hIcon;
  int   iIcon;
  DWORD dwAttributes;
  TCHAR szDisplayName[MAX_PATH];
  TCHAR szTypeName[80];
} SHFILEINFO;
  • LPTStrこの文字列を保持するためだけに特別なメモリブロックを割り当てた場合(通常はまたは同様のもの)に使用し、そのアンマネージメモリ領域にMarshal.AllocHGlobalコピーします。string

  • ByValTStrメモリ内の別の領域を参照するのではなく、実際の文字列を値で文字通り渡す場合に使用します。

構造体は、ポインターではなく、適切な値を必要としています。

于 2013-03-01T20:12:37.680 に答える
0

これは古い質問だと思いますが、これは突然頻繁にポップアップし始めたように見えるクラッシュを解決するのに役立ちました. Windows Update を介して .NET 4.5.2 の更新プログラムが展開された後、これらの問題が発生し始めたようです。 LPTStr更新前に機能し、更新ByValTStr後に機能しました。

于 2015-08-07T21:33:31.480 に答える