2011-01-21 2 views
2

Я недавно работал с ресурсами из вторичных библиотек/двоичных модулей и обнаружил странную ошибку.Проблема EnumResourceNames - неизвестная ошибка

У меня есть два родных ссылки WinAPI:

[DllImport("kernel32.dll", SetLastError = true)] 
public extern static bool EnumResourceNames(IntPtr hModule, int lpszType, EnumResNameProc lpEnumFunc, IntPtr lParam); 

[DllImport("kernel32.dll", SetLastError=true)] 
public extern static IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, int dwFlags); 

Когда я звоню LoadLibraryEx, я получаю экземпляр IntPtr - именно то, что мне нужно:

IntPtr x = WinApi.LoadLibraryEx(@"D:\Software\Reflector\Reflector.exe",IntPtr.Zero,2); 
Debug.WriteLine(x.ToInt32()); 

Однако, когда я пытаюсь перечислить иконку ресурсы (определены ID = 3):

Debug.WriteLine(WinApi.EnumResourceNames(x, 3, new EnumResNameProc(ListCallback), IntPtr.Zero)); 
Debug.WriteLine(Marshal.GetLastWin32Error()); 

Я получаю этот код ошибки (возвращается b у GetLastError):

-532462766

Это обычно означает, что существует неизвестная ошибка, насколько я знаю, но я просто любопытно - что может быть проблема с распечаткой ресурсы из исполняемого файла?

+0

Является ли EnumResourceNames() фактическим возвратом false? Если он возвращает true, значение GetLastError() не имеет смысла. – Luke

+0

Управляется или неуправляемая DLL? –

+0

Возвращается False - это, по-видимому, терпит неудачу. Это управляемое приложение C#, вызывающее неуправляемую DLL (kernel32). –

ответ

4

-532462766 == 0xe0434352. Последние три шестнадцатиричных пара заклинания «CCR» - общий трюк, который программисты Microsoft используют, чтобы попытаться найти легко узнаваемый код исключения. Точный смысл таинственный, за которым он обычно связан с управляемым кодом и, по-видимому, очень низким уровнем в подсистеме, которая обычно не создает значимого управляемого исключения.

Существует прекрасная кандидатская причина этого загадочного исключения, ваша декларация Pinum для EnumResources неверна. Второй аргумент - IntPtr, а не int. Это имеет некоторые шансы на переход kaboom в 64-битную операционную систему.

Пожалуйста, отправьте сообщение, если вы когда-нибудь выясните, что означает CCR.


using System; 
using System.ComponentModel; 
using System.Runtime.InteropServices; 
using System.Diagnostics; 

class Program { 
    static void Main(string[] args) { 
     try { 
      IntPtr module = LoadLibraryEx(@"C:\windows\system32\user32.dll", IntPtr.Zero, 2); 
      if (module == IntPtr.Zero) throw new Win32Exception(); 
      if (!EnumResourceNames(module, (IntPtr)3, new EnumResNameProc(ListCallback), IntPtr.Zero)) 
       throw new Win32Exception(); 
     } 
     catch (Win32Exception ex) { 
      Console.WriteLine(ex.Message); 
     } 
     Console.ReadLine(); 
    } 

    static bool ListCallback(IntPtr hModule, IntPtr type, IntPtr name, IntPtr lp) { 
     long idorname = (long)name; 
     if (idorname >> 16 == 0) Console.WriteLine("#{0}", idorname); 
     else Console.WriteLine(Marshal.PtrToStringAnsi(name)); 
     return true; 
    } 

    public delegate bool EnumResNameProc(IntPtr hModule, IntPtr type, IntPtr name, IntPtr lp); 
    [DllImport("kernel32.dll", SetLastError = true)] 
    public extern static bool EnumResourceNames(IntPtr hModule, IntPtr type, EnumResNameProc lpEnumFunc, IntPtr lParam); 
    [DllImport("kernel32.dll", SetLastError = true)] 
    public extern static IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, int dwFlags); 
} 
+0

Я считаю, что CCR является одним из оригинальных имен для CLR. – Gabe

+0

Хм ... Согласно документам MSDN, у меня есть правильная подпись для методов, упомянутых выше. Согласно PInvoke.net (http://www.pinvoke.net/default.aspx/kernel32.enumresourcenames), я также использую правильную подпись. Все еще пытаюсь понять, что означает CCR. –

+1

Нет, это определенно неправильно. Типичный для pinvoke.net, чтобы получить это как неправильно, так и прямо на одной странице, нет редактора, чтобы избавиться от ошибок. Объявление SDK использует LPCTSTR, это указатель. IntPtr в управляемом коде. Вы используете MAKEINTRESOURCE в коде C для преобразования int в указатель. Вы используете (IntPtr) 3 в своем коде C# для достижения того же. –

0

Hans Passant имеет это правильно, но более подробную информацию о сообщении об ошибке, 0xe0434352 является родовым код ошибки для исключения .NET. Если вы запустите это из отладчика Visual Studio, вы увидите, что System.ArgumentException поднимается, когда EnumResourceNames пытается вызвать обратный вызов. Сообщение об ошибке:

Указатель, переданный как строка, не должен находиться в нижней части 64K адресного пространства процесса.

Это исключение попадает в список EnumResourceNames и превращается в сбой. Решение, как показало Ганс, заключается в том, что функция обратного вызова должна принимать второй и третий параметры как IntPtr, а не строку.

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