10

MSDN で、2 つの属性について次の説明を見つけました。

PreserveSig PreserveSig フィールドを true に設定して、管理されていない署名を HRESULT または retval 値で直接変換します。HRESULT または retval 値を例外に自動的に変換するには、false に設定します。デフォルトでは、PreserveSig フィールドは true です。

SetLastError呼び出し元が Marshal.GetLastWin32Error API 関数を使用して、メソッドの実行中にエラーが発生したかどうかを判断できるようにします。Visual Basic では、デフォルトは true です (オーバーヘッドがいくらか追加されます)。C# および C++ では、デフォルトは false です。

私の質問は次のとおりです。これら 2 つは互いにどのように関係していますか? PreserveSig を「false」に設定したとします。これは、HRESULT を例外に変換する必要があることを意味します。アンマネージ関数がエラーまたはエラーが発生しなかったことを示す整数を返す場合、これをどのように例外に変換できますか?

また、PreserveSig を使用して例外を抽出できたのに、なぜ GetLastWin32Error メソッドを呼び出す必要があるのでしょうか。

よろしくお願いしますPK

4

1 に答える 1

18

Win32 関数が を返すことはほとんどありませんHRESULT。代わりに、BOOLエラーを示すために を返すか、特別な値を使用します (例: をCreateFile返しますINVALID_HANDLE_VALUE)。エラー コードはスレッドごとの変数に格納されます。この変数は で読み取ることができますGetLastError()SetLastError=trueネイティブ関数が戻った後にこの変数を読み取るようにマーシャラーに指示し、エラー コードを後で読み取ることができる場所に隠しますMarshal.GetLastWin32Error()。これは、.NET ランタイムが舞台裏で他の Win32 関数を呼び出し、p/invoke 呼び出しからのエラー コードを検査する機会を得る前に台無しにする可能性があるというものです。

HRESULTa (または同等のもの、たとえば)を返す関数NTSTATUSは、Win32 関数とは異なる抽象化レベルに属します。通常、これらの関数は COM 関連 (Win32 以上) または COM 関連 (Win32ntdll以下) であるため、Win32 の最終エラー コードは使用しません (ただし、内部で Win32 関数を呼び出す場合があります)。

PreserveSig=falseマーシャラーに戻り値をチェックし、HRESULTそれが成功コードでない場合は、HRESULT. DllImported 関数のマネージ宣言にはvoid、戻り値の型があります。

C# または VB コンパイラはDllImported 関数のアンマネージ シグネチャをチェックできないため、指定された内容を信頼する必要があることに注意してください。PreserveSig=false以外のものを返す関数を使用すると、奇妙な結果がHRESULT得られます (例: ランダムな例外)。SetLastError=true最後の Win32 エラー コードを設定しない関数を使用すると、有用なエラー コードの代わりにガベージが返されます。

于 2009-04-18T17:26:42.340 に答える