Marshal::GetLastWin32Error have unpredictable result

Hey guys, I am working on a windows app build with unity3d. I try to pinvoke some user32.dll function and try to call Marshal::GetLastWin32Error() to get error code if there is any.

I followed the guide line in those two pages: call Marshal::GetLastWin32Errorcall() instead of kernal32.dll’s GetLastError and call it immediately after a user32 function call.

Marshal.GetLastWin32Error Method (System.Runtime.InteropServices) | Microsoft Learn
GetLastError function (errhandlingapi.h) - Win32 apps | Microsoft Learn

My app worked just fine until I add Marshal::GetLastWin32Error call. Marshal::GetLastWin32Error just get some random errors.

Can any help me with this problem? I am really confused .
Thanks.

Are you setting the “SetLastError” property in your DllImport attribute? DllImportAttribute.SetLastError Field (System.Runtime.InteropServices) | Microsoft Learn

You shouldn’t call Marshal.SetLastWin32Error() yourself. Use Marshal.GetLastWin32Error() after calling the P/Invoke function.

Oops it is typo, I am actully call Marshal.GetLastWin32Error();

This is how I define those function.

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

and my function is like:

var progman = User32.FindWindow(PROGMAN, null);
var errorCode = Marshal.GetLastWin32Error();
if (errorCode != 0)
       UnityEngine.Debug.LogException(new Win32Exception(errorCode));

Counld that be the error code from other program? I don’t know if this function is multi-thread safe.

No, it's stored in a thread local variable. However, I see an error in your usage of FindWindow: you are only supposed to call GetLastWin32Error() if FindWindow function fails. It will not set the error if it succeeds, so you might be seeing an error from a previous call to something else. Try this:

var progman = User32.FindWindow(PROGMAN, null);
if (progman == IntPtr.Zero)
    UnityEngine.Debug.LogException(new Win32Exception(Marshal.GetLastWin32Error()));

Oh, Thanks! I will try this one. Get back to this if it works.