这个pinvoke出了什么问题?

时间:2011-06-10 22:07:35

标签: c# pinvoke

我有这段代码没有被修改但突然间它已经停止工作......我可以发誓它曾经工作但不能保证。它引发了一个例外:

  

尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

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 个答案:

答案 0 :(得分:4)

我在我的机器上测试时,您的代码运行正常。顺便说一下,你有什么理由不喜欢下面的方法,它有点短,并达到了相同的目标:

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

当然在幕后Win32Exception PInvokes到FormatMessage但至少它是.NET框架应该担心它,而不是我们。


更新:

以下是在.NET中实现Win32Exception.GetErrorMessage方法的方法:

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

答案 1 :(得分:0)

尝试sMsg = Marshal.PtrToStringUni(pMessageBuffer,dwBufferLength);