DllImport - PreserverSig 属性と SetLastError 属性
質問
MSDN で、2 つの属性について次の説明を見つけました。
署名を保存 HRESULT または retval 値を使用してアンマネージ署名を直接変換するには、PreserveSig フィールドを true に設定します。HRESULT または retval 値を例外に自動的に変換するには、これを false に設定します。デフォルトでは、PreserveSig フィールドは true です。
SetLastError 呼び出し元が Marshal.GetLastWin32Error API 関数を使用して、メソッドの実行中にエラーが発生したかどうかを判断できるようにします。Visual Basic では、デフォルトは true (オーバーヘッドが追加されます) です。C# および C++ では、デフォルトは false です。
私の質問は次のとおりです。この二人はどのような関係にあるのでしょうか?PreserveSig を「false」に設定しているとします。これは、HRESULT を例外に変換する必要があることを意味します。アンマネージ関数がエラーが発生したか、エラーが発生しなかったことを示す整数を返した場合、これを例外に変換するにはどうすればよいでしょうか。
また、PreserveSig を使用して例外を何とか抽出できた場合、なぜ GetLastWin32Error メソッドを呼び出す必要があるのでしょうか?
PKをよろしくお願いします
解決
Win32 関数が を返すことはほとんどありません。 HRESULT
. 。代わりに、彼らは BOOL
または、特別な値を使用してエラーを示します (例: CreateFile
戻り値 INVALID_HANDLE_VALUE
)。エラー コードはスレッドごとの変数に保存され、次のコマンドで読み取ることができます。 GetLastError()
. SetLastError=true
ネイティブ関数が戻った後にこの変数を読み取り、後で読み取ることができる場所にエラー コードを隠しておくようにマーシャラーに指示します。 Marshal.GetLastWin32Error()
. 。これは、.NET ランタイムが裏で他の Win32 関数を呼び出し、検査する前に p/invoke 呼び出しからのエラー コードを台無しにする可能性があるという考えです。
を返す関数 HRESULT
(または同等のもの、例: NTSTATUS
) は、Win32 関数とは異なる抽象化レベルに属します。通常、これらの関数は COM 関連 (Win32 以上)、または ntdll
(Win32 より下)そのため、Win32 の最終エラー コードは使用されません(ただし、内部で Win32 関数を呼び出す可能性があります)。
PreserveSig=false
マーシャラーにリターンを確認するように指示します HRESULT
成功コードでない場合は、次のコードを含む例外を作成してスローします。 HRESULT
. 。あなたの管理された宣言 DllImport
ed 関数は次のようになります void
戻り値の型として。
C# または VB コンパイラではチェックできないことに注意してください。 DllImport
ed 関数のアンマネージ署名であるため、関数はユーザーの指示をすべて信頼する必要があります。置いたら PreserveSig=false
以外のものを返す関数の場合 HRESULT
, 、奇妙な結果が得られます (例:ランダムな例外)。置いたら SetLastError=true
最後の Win32 エラー コードを設定しない関数では、有用なエラー コードではなくガベージが返されます。