2013-03-01 2 views
1

У нас есть вид дерева в приложении Windows Forms, в котором отображаются файлы с использованием соответствующего значка файла, используя следующий код. Моя проблема заключается в том, что вызов GetIcon(), похоже, повреждает мою память, когда я начинаю получать различные сбои программ, которые я не могу уловить с помощью отладчика после этого вызова.
Программа работает, когда я меняю managedType.LPTStr на managedType.ByValTStr. Является ли это истинным исправлением или просто маскирует проблему?Может ли использовать UnmanagedMemory.LPTStr вместо .ByValTStr привести к повреждению памяти? Зачем?

Этот код, казалось, работал в нашей последней версии продукта, и я не вижу ничего, что изменилось. Использование .NET 4.0. Я вижу проблему только в режиме Release.

[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); 
     } 

ответ

0

Ну, это не собственно LPStr в структуры, так что вы не можете попытаться выстроить его как единое целое и ожидать, что она работает:

typedef struct _SHFILEINFO { 
    HICON hIcon; 
    int iIcon; 
    DWORD dwAttributes; 
    TCHAR szDisplayName[MAX_PATH]; 
    TCHAR szTypeName[80]; 
} SHFILEINFO; 
  • LPTStr вы используете, когда вам Я выделил специальный блок памяти только для того, чтобы удерживать эту строку (обычно в Marshal.AllocHGlobal или аналогичной), затем вы скопировали свой string в эту неуправляемую область памяти.

  • ByValTStr Вы используете, когда вы буквально передаете фактическую строку по значению, а не ссылку на другую область памяти.

Структуру требуется правильное значение, а не указатель.

+0

Спасибо. Коллега только что пришел и объяснил это, прежде чем я прочитал вам ответ, и я собирался ответить на него сам. – Kim

0

Я понимаю, что это старый вопрос, но это помогло мне решить крушение, которая, казалось, внезапно начала появляться чаще, чем нет. Похоже, что я начал сталкиваться с этими проблемами после обновления .NET 4.5.2 с помощью Центра обновления Windows. LPTStr работал до обновления и ByValTStr работал после.

+0

Если бы вопрос помог, просто поднимите вопрос, а не добавьте ответ :) – Kim

Смежные вопросы