开发者

What is wrong with this pinvoke?

开发者 https://www.devze.com 2023-03-12 17:02 出处:网络
I have this piece of code that has not been modified but all of a sudden it has stopped working... I could swear that it used to work but can\'t guarantee it. It throws an exception:

I have this piece of code that has not been modified but all of a sudden it has stopped working... I could swear that it used to work but can't guarantee it. It throws an exception:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

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", Ch开发者_开发问答arSet = 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.";
    }
}

What am I doing wrong here, I can't seem to find anything? Thanks!


Your code worked fine when I tested it on my machine. By the way is there any reason you wouldn't prefer the following method which is a little shorter and achieves equivalent goal:

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

Of course under the covers Win32Exception PInvokes into FormatMessage but at least it's the .NET framework that should worry about it, not us.


UPDATE:

Here's how the Win32Exception.GetErrorMessage method is implemented in .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;
}

where FormatMessage is declared like this:

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


Try sMsg = Marshal.PtrToStringUni(pMessageBuffer, dwBufferLength);

0

精彩评论

暂无评论...
验证码 换一张
取 消