0

我有一点点代码。

[DllImport("library.dll", EntryPoint = "SomeoneElsesReadFunction")]
[return: MarshalAs(UnmanagedType.U4)]
private static extern UInt32 SomeoneElsesReadFunction(
    Int16[] data,
    Int16[] dataOrig,
    [MarshalAs(UnmanagedType.U2)]
    Int16 buffsize,
    ref int smpNum,
);

然后...

var returnCode = SomeoneElsesReadFunction(Buffer, OrigBuffer, Consts.BufferSize, ref _sampleNumber);

int errorCode;

if ((errorCode = Marshal.GetLastWin32Error()) != 0)
{
    throw new Exception(string.Format("Device read failed. Windows System Error Code: {0}", errorCode));
}

这发生在每秒运行多次的更广泛的循环中。

errorCode在循环的每次迭代中都得到 183 分。当我签入 VS 调试器时,我可以看到调用前的最后一个 Win32 错误是 183,SomeoneElsesReadFunction()之后仍然是 183。

但是有没有办法在调用方法之前清除/重置这个值,所以我可以确定,当我事后检查时,错误肯定发生在每次调用的方法中,而不是前一次调用遗留下来的?

编辑

为了澄清与 的混淆,returnCode由于某种原因,即使在我需要检查的特定错误条件下,原始方法也会返回 code = 0 。因此,GetLastWin32Error()即使 returnCode 为 0(OK),我也需要调用。

4

2 回答 2

0

感谢@Jake对我能够解决此问题的问题的评论。在某些版本的 Windows™ 上, 的行为GetLastWin32Error()是不可预测的。我发现以前的 WIN32 调用中的错误没有被后续成功的 WIN32 调用清除。因此,在未先清除错误代码的情况下在稍后调用后进行检查时会出现误报。

internal static class WIN32
{
    [DllImport("kernel32.dll")]
    internal static extern bool AllocConsole();

    [DllImport("kernel32.dll")]
    internal static extern IntPtr GetConsoleWindow();

    [DllImport("user32.dll", SetLastError = true)]
    internal static extern void SetLastErrorEx(uint dwErrCode, uint dwType);
}

请注意,我的一些导入没有, SetLastError = true参数。添加此改进的错误代码一致性,但不完全。

那么后来,...

// clear any previous WIN32 error code, otherwise
WIN32.SetLastErrorEx(0, 0);
IntPtr hWnd = WIN32.GetConsoleWindow();
if (Marshal.GetLastWin32Error() > 0) { /* do something */ }
if (hWnd == IntPtr.Zero) 
{
    WIN32.SetLastErrorEx(0, 0);
    WIN32.AllocConsole();
    if (Marshal.GetLastWin32Error() > 0) { /* do something else */ }
}
于 2021-06-02T16:12:28.220 回答
0

我认为您混淆了错误代码和返回值。 SetLastError应该只在函数产生错误时调用,它不应该这样做SetLastError(0)。作为开发人员,您的工作是检查函数调用是否失败,然后找出失败的原因

错误代码是有关函数失败原因的额外信息,但您的代码不会检查返回值以查看是否存在失败

var returnCode = SomeoneElsesReadFunction(Buffer, OrigBuffer, Consts.BufferSize, ref _sampleNumber);

if(!returnCode) // Did it fail?
{
    int errorCode;

    if ((errorCode = Marshal.GetLastWin32Error()) != 0) // Why did it fail?
    {
        throw new Exception(string.Format("Device read failed. Windows System Error Code: {0}", errorCode));
    } 
}
于 2018-09-28T09:16:44.973 回答