I tried a dozen different things to get this to work, wasting most of a day, and finally asked an expert for help. Before looking at the answer, you might want to see if you can spot my mistake.
The expert told me how to write the DLLImport
correctly (well, almost correctly) off the top of his head, and then asked, by the way, was there any special reason why I wasn't using the System.Environment.Username property
. Well, duh! I'd completely overlooked the System.Environment
class in the .NET Framework, which provides all the information I happened to want for that part of my program.
Even though I wound up using the System.Environment
class in my program, it's useful to look at the full, correct P/Invoke
call to GetUserName
public static extern bool GetUserName
ref int nSize);
static void Main(string args)
StringBuilder b=new StringBuilder(100);
bool rc=GetUserName(b, ref n);
What's changed? Two things: one that matters, and one that doesn't matter quite so much. The one that matters is that the second argument to GetUserName
needs to be a reference in C#, since the underlying API calls for an LPDWORD
, in other words for a pointer to a DWORD
What was the other change? The best C# type to use for the LPTSTR lpBuffer
argument of the underlying API call is a StringBuilder
, not a Byte
. The StringBuilder
returned is directly usable as a string; the Byte
would have to be explicitly converted.
If I'd had more experience with DllImport
, I might have realized that the System.NullReferenceException
I got originally was telling me that it needed a reference type where I was passing a value type. Of course, the bug wasn't where I was looking, because I was looking at the wrong place.
There's a rule or three you can take away from this example. The first rule is that a Win32 pointer type translates to a corresponding .NET reference type. The second rule is that a Win32 string pointer generally translates to a .NET StringBuilder
type (or, sometimes, to a String
type). The third rule is to look for a pointer/value mismatch if you get a System.NullReferenceException
from a P/Invoke