为了保持与编程语言无关,Windows COM 系统和许多 Windows API 返回一种 4 字节整数类型,称为 HRESULT
,用来指示 API 是成功还是失败,并提供有关失败的一些信息。 需要传递给调用方的其他值通过充当“out”参数的指针参数“返回”,通常是签名中的最后一个参数。 C# 和 Visual Basic 等语言传统上将故障代码转换为异常,以便与该语言对失败通常的传播方式相匹配,并期望互操作方法签名不包括 HRESULT
。 若要将方法签名转换为本机格式的签名,运行时将方法的返回值移至具有更高间接级别的“out”参数(换句话说,使其成为一个指针,指向托管签名的返回类型),并假定一个 HRESULT
返回值作为默认值。 如果托管方法返回 void
,则不添加其他参数,并且返回值变为一个 HRESULT
。 例如,请参阅以下两种转换为同一本机签名的 C# COM 方法:
int Add(int a, int b);
void Add(int a, int b, out int sum);
HRESULT Add(int a, int b, /* out */ int* sum);
COM 中的 PreserveSig
C# 中的所有 COM 方法都默认使用已转换的签名。 将 HRESULT
添加到 COM 接口方法中,以便在不使用签名转换和处理 PreserveSigAttribute 值的情况下使用和导出方法。 当属性应用于方法时,不会对方法签名执行任何转换,同时也不会因 HRESULT
值失败而抛出异常。 这适用于内置的 COM 和源生成的 COM。 例如,请参阅以下 C# 方法签名,其中包含属性 PreserveSig
及其相应的本机签名。
[PreserveSig]
int Add(int a, int b, out int sum);
HRESULT Add(int a, int b, int* sum);
如果该方法可能返回不同 HRESULT
值(不是失败,但必须以不同的方式处理)则此方法非常有用。 例如,当方法不失败但只返回部分结果时,某些方法可能会返回值 S_FALSE
,当 S_OK
该方法返回所有结果时。
PreserveSig
和 P/Invokes
DllImportAttribute属性还具有与bool PreserveSig
类似的PreserveSigAttribute
字段,但默认为true
。 若要指示运行时转换托管签名并处理返回的 HRESULT
,请在 PreserveSig
中将 false
字段设置为 DllImportAttribute
。 例如,请参阅以下对同一本机方法的两个 P/Invokes 的签名,其中一个具有 PreserveSig
,设置为 false
,另一个保留为默认 true
值。
[DllImport("shlwapi.dll", EntryPoint = "SHAutoComplete", ExactSpelling = true, PreserveSig = false)]
public static extern void SHAutoComplete(IntPtr hwndEdit, SHAutoCompleteFlags dwFlags);
[DllImport("shlwapi.dll", EntryPoint = "SHAutoComplete", ExactSpelling = true)]
public static extern int SHAutoCompleteHRESULT(IntPtr hwndEdit, SHAutoCompleteFlags dwFlags);
注释
源生成的 P/Invokes 使用 LibraryImportAttribute,没有 PreserveSig
字段。 生成的代码始终假定本机签名和托管签名相同。 有关详细信息,请参阅源生成的 P/Invokes。
手动处理 HRESULT
值
调用返回PreserveSig
的HRESULT
方法时,可以在ThrowExceptionForHR指示失败时使用HRESULT
方法抛出相应的异常。 同样,在实现 PreserveSig
方法时,可以使用 GetHRForException 该方法返回 HRESULT
指示异常的相应值。
将 HRESULT 封送为结构
使用PreserveSig
方法时,int
应为HRESULT
的托管类型。 但是,使用自定义 4 字节结构作为返回类型,可以定义帮助程序方法和属性,这些方法和属性可以简化使用 HRESULT
。 在内置封送中,这是自动工作的。 要在源生成的封送中使用结构代替 int
作为 HRESULT
的托管表示,请添加以 MarshalAsAttribute 为参数的 Error 属性。 此属性的存在将 HRESULT
位重新解释为结构。