Reputation: 3616
I have this little bit of code.
[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,
);
then...
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));
}
which takes place within a wider loop running multiple times per second.
I keep getting an errorCode
of 183 on every iteration of the loop. When I check in the VS debugger, I can see the Last Win32 Error is 183 before calling SomeoneElsesReadFunction()
and still 183 afterwards.
But is there a way of clearing/resetting this value before the method is called, so I can be sure, when I check afterwards, that the error is definitely occurring within the method with each call and not just left over from a previous call?
Edit
To clarify the confusion with the returnCode
, the original method for some reason returns a code = 0 even in a particular error condition that I need to check. For this reason I need to call GetLastWin32Error()
even if the returnCode is 0 (OK).
Upvotes: 2
Views: 989
Reputation: 1358
Thanks to @Jake's comment on the question I was able to resolve this issue. On some version of Windows™, The behavior of GetLastWin32Error()
is unpredictable. I was finding that the errors from previous WIN32 calls were not being cleared by subsequent, successful WIN32 calls. Thus a false negative when checking after a later call without first clearing the error code.
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);
}
Note that some of my imports do not have the , SetLastError = true
parameter. Adding this improved error code consistency, but not entirely.
then later, ...
// 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 */ }
}
Upvotes: 0
Reputation: 11889
I think you are confusing error codes and return values. SetLastError
should only be called when a function generates an error, it should never do SetLastError(0)
. It's your job as a developer to check if a function call failed and then work out why it failed.
The error code is extra information about why a function failed, but your code isn't checking the return value to see if there was a failure.
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));
}
}
Upvotes: 1