Win10 x64 1809 の VS2019 で .NET 4.6 で C# を使用しています。
P/Invoke を使用している場合、「Marshal.GetLastWin32Error()」行にブレークポイントを設定すると、最後に設定された Win32 エラー コードが変更されているようです。
例えば:
using System.Runtime.InteropServices;
namespace PInvoke
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void SetLastError(
uint dwErrCode
);
static void Main(string[] args)
{
int startErr = Marshal.GetLastWin32Error();
SetLastError(500);
int endError = Marshal.GetLastWin32Error();
return;
}
}
}
「return」にブレークポイントを設定すると、実行を繰り返すと endError が 500 と表示されます。
ただし、「int endError = Marshal.GetLastWin32Error();」にブレークポイントを設定すると、繰り返し実行すると endError が 0 として表示されます。
「Marshal.GetLastWin32Error()」行にブレークポイントを設定すると、別の領域のように予期しない結果が生じるようです。P/Invoking SetupEnumInfSections() は 259 (ERROR_NO_MORE_ITEMS) を期待していましたが、ブレークポイントを設定すると、代わりに 1008 を受け取ります。
- 私のプロジェクトでこの動作を引き起こしている何かが欠けていますか? (私は CodeProject と GitHub からの個人およびサードパーティの両方のさまざまなプロジェクトを試しましたが、この動作を引き続き経験しています)
- これは Visual Studio のエラーですか (これを報告する必要がありますか?)
- これは期待されていますか?(下記参照)
Marshal.GetLastWin32Error() の呼び出しは、問題の API 呼び出しの直後に呼び出す必要があることを認識していました (API 呼び出しが実際に最後のエラーを設定し、P/Invoke 呼び出しの場合、デコレータに "SetLastError = true" が含まれていると仮定します)。 )、追加の呼び出しによって最後のエラーの値が変更される可能性があるためです。
ただし、デバッグ、Marshal.GetLastWin32Error() でのブレークポイントの設定などに関して、他の種類の警告は見つかりませんでした。
これは、GetLastError() を使用してすぐに API 呼び出しを実行し、デコレータ ("SetLastError = true") を設定するのと同様に、VS で P/Invoke を作成する開発者が注意する必要がある「落とし穴」ですか? それは「落とし穴」かもしれませんが、そうであれば、VS(および/またはデバッガー)を含む各プロセスに独自の最後のエラーがあると予想されるため、すぐにはわかりませんが、基礎となるアプリケーションに関連付けられている可能性がありますなんらかの方法で、私は気づいていません。