I tested a lot. But I found no disadvantages of those 2!
But see the accepted answer.
I read here that calling
GetLastError in managed code is unsafe because the Framework might internally "overwrite" the last error. I have never had any noticeable problems with GetLastError and it seems for me that the .NET Framework is smart enough not to overwrite it. Therefore I have a few questions on that topic:
- in
[DllImport("kernel32.dll", SetLastError = true)]does theSetLastErrorattribute make the Framework store the error code for the use ofMarshal.GetLastWin32Error()? - is there an example where plain
GetLastErrorfails to give the correct result ? - do I really HAVE to use
Marshal.GetLastWin32Error()? - is this "problem" Framework version related ?
public class ForceFailure
{
[DllImport("kernel32.dll")]
static extern uint GetLastError();
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);
public static void Main()
{
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
System.Console.WriteLine("It worked???");
else
{
// the first last error check is fine here:
System.Console.WriteLine(GetLastError());
System.Console.WriteLine(Marshal.GetLastWin32Error());
}
}
}
Producing errors:
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
Console.WriteLine("It worked???");
else
{
// bad programming but ok GetlLastError is overwritten:
Console.WriteLine(Marshal.GetLastWin32Error());
try
{
using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
}
catch { }
Console.WriteLine(GetLastError());
}
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
Console.WriteLine("It worked???");
else
{
// bad programming and Marshal.GetLastWin32Error() is overwritten as well:
Console.WriteLine(GetLastError());
try
{
using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
}
catch { }
Console.WriteLine(Marshal.GetLastWin32Error());
}
// turn off concurrent GC
GC.Collect(); // doesn't effect any of the candidates
Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(Marshal.GetLastWin32Error());
Console.WriteLine(Marshal.GetLastWin32Error());
// when you exchange them -> same behaviour just turned around
I don't see any difference! Both behave the same except Marshal.GetLastWin32Error stores results from App->CLR->WinApi calls as well and GetLastError stores only results from App->WinApi calls.
Garbage Collection seems not to call any WinApi functions overwriting the last error code
- GetLastError is thread-safe. SetLastError stores an error code for each thread calling it.
- since when would GC run in my threads ?
GetLastErrorworks, possibly it works in all existing .NET Framework versions and implementations. So, your code is working, but this doesn't prove anything. .NET Framework developers are free to change .NET implementation by the way, thatGetLastErrorwill stop work one day. - Alex FGetLastWin32Errorworks correctly. You want to useGetlastErrorhack, possibly it will always work, but this is still hack. So, the question is somewhat philosophical: can we use hacks, if it is not proved, that it is incorrect. - Alex F