質問

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. 。あなたの管理された宣言 DllImported 関数は次のようになります void 戻り値の型として。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top