Что не так с этим pinvoke? - PullRequest
0 голосов
/ 11 июня 2011

У меня есть этот кусок кода, который не был изменен, но внезапно он перестал работать ... Я могу поклясться, что раньше он работал, но не могу этого гарантировать. Выдает исключение:

Попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена.

static void Main(string[] args)
{
    ErrorMsg(123);
}

[DllImport("kernel32.dll", EntryPoint = "FormatMessageW", CharSet = CharSet.Auto)]
static extern int FormatMessage(int dwFlags, IntPtr lpSource, long dwMessageId, int dwLanguageId, out IntPtr MsgBuffer, int nSize, IntPtr Arguments);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetThreadLocale();

/// <summary>
/// Gets a Locale specific windows error
/// code specified.
/// </summary>
/// <param name="errorcode">The errorcode.</param>
public static string ErrorMsg(long errorcode)
{
    try
    {
        if (errorcode == 0)
            return "No Error";
        IntPtr pMessageBuffer;
        int dwBufferLength;
        string sMsg;
        int dwFormatFlags;
        //FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS
        dwFormatFlags = 0x00000100 | 0x00000200 | 0x00001000;
        dwBufferLength = FormatMessage(dwFormatFlags, IntPtr.Zero, errorcode, GetThreadLocale(), out pMessageBuffer, 0, IntPtr.Zero);
        if (dwBufferLength == 0)
            return "An Unknown Error Has occured.";
        sMsg = Marshal.PtrToStringUni(pMessageBuffer);
        Marshal.FreeHGlobal(pMessageBuffer);
        return sMsg;
    }
    catch (Exception ex)
    {
        return "An Unknown Error Has occured.";
    }
}

Что я здесь не так делаю, кажется, я ничего не могу найти? Спасибо!

Ответы [ 2 ]

4 голосов
/ 11 июня 2011

Ваш код работал нормально, когда я тестировал его на своей машине. Кстати, есть ли причина, по которой вы бы не предпочли следующий метод, который немного короче и достигает эквивалентной цели:

static void Main()
{
    var ex = new Win32Exception(123);
    Console.WriteLine(ex.Message);
}

Конечно, под прикрытием Win32Exception P вызывает в FormatMessage но, по крайней мере, об этом должны беспокоиться .NET Framework, а не мы.


UPDATE:

Вот как метод Win32Exception.GetErrorMessage реализован в .NET:

private static string GetErrorMessage(int error)
{
    string result = "";
    StringBuilder stringBuilder = new StringBuilder(256);
    int num = SafeNativeMethods.FormatMessage(12800, NativeMethods.NullHandleRef, error, 0, stringBuilder, stringBuilder.Capacity + 1, IntPtr.Zero);
    if (num != 0)
    {
        int i;
        for (i = stringBuilder.Length; i > 0; i--)
        {
            char c = stringBuilder[i - 1];
            if (c > ' ' && c != '.')
            {
                break;
            }
        }
        result = stringBuilder.ToString(0, i);
    }
    else
    {
        result = "Unknown error (0x" + Convert.ToString(error, 16) + ")";
    }
    return result;
}

где FormatMessage объявлено так:

[DllImport("kernel32.dll", BestFitMapping = true, CharSet = CharSet.Auto, SetLastError = true)]
public static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId, StringBuilder lpBuffer, int nSize, IntPtr arguments);
0 голосов
/ 11 июня 2011

Попробуйте sMsg = Marshal.PtrToStringUni (pMessageBuffer, dwBufferLength);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...