L'attributo [DllImport] che normalmente utilizziamo con PInvoke permette di stabilire se un eventuale errore deve essere corredato da informazioni estese che possiamo recuperare attraverso l'API GetLastError e la relativa FormatMessage per ottenere l'equivalente testuale del codice di errore.
L'utilizzo della GetLastError non e' pero' corretto in quanto non e' detto (essendoci il CLR di mezzo) che non siano state chiamate altre API dopo la nostra funzione e della quale vogliamo recuperare il codice di errore.
Il .NET Framework mette pero' a disposizione tutto il necessario per accedere nel modo corretto al codice di errore settato dalla nostra API attraverso la funzione Marshal.GetLastWin32Error().
La funzione citata risolve pero' solo in parte il problema in quanto sapere che la chiamata alla funzione xyz ha generato un errore -23421 non e' molto d'aiuto, grazie pero' alla classe Win32Exception presente in System.ComponentModel possiamo ottenere direttamente la descrizione dell' errore in base al codice di errore passatogli nel costruttore (in pratica 'wrappa' la FormatMessage...).
Ma non e' finita!, il costruttore di default della Win32Exception invoca direttamente Marshal.GetlastWin32Error() percui generare un eccezione che include tutti i dettagli del problema quando si ha a che fare con le Win32 API si riduce a generare un eccezione di tipo Win32Exception() e utilizzare le varie proprieta' tipo Message e NativeErrorCode per recuperare tutti i dettagli.
Tutto questo vale ovviamente se abbiamo impostato SetLastError=true nell'attributo DllImport oppure se utilizziamo l'enunciato Declare di VB.NET il quale setta automaticamente LastError=True. 

Ecco un esempio pratico:

[DllImport("user32.dll",SetLastError=true)] static extern Int32 GetWindowText (IntPtr hWnd, System.Text.StringBuilder lpString, Int32 cch);

System.Text.StringBuilder sb=new System.Text.StringBuilder(260);
// Creo un handle invalido giusto per far fallire la chiamata...
IntPtr hWnd=new IntPtr(-1);
Int32 RetCode=GetWindowText(hWnd,sb,sb.Capacity);
if (RetCode==0)
{
throw new Win32Exception();
}