CA1404:紧接在 P/Invoke 之后调用 GetLastError
适用范围:Visual Studio
Visual Studio for Mac
Visual Studio Code
项 | “值” |
---|---|
RuleId | CA1404 |
Category | Microsoft.Interoperability |
重大更改 | 非中断 |
原因
对 System.Runtime.InteropServices.Marshal.GetLastWin32Error 方法或等效的 Win32 GetLastError
函数进行调用,并且紧接在此之前的调用不是对平台 invoke 方法的调用。
规则说明
平台调用方法访问非托管代码,并使用 Visual Basic 中的 Declare
关键字或 System.Runtime.InteropServices.DllImportAttribute 属性进行定义。 通常,在失败时,非托管函数调用 Win32 SetLastError
函数来设置与失败关联的错误代码。 失败函数的调用方调用 Win32 GetLastError
函数来检索错误代码并确定失败的原因。 错误代码基于每个线程进行维护,并被下一次调用 SetLastError
覆盖。 调用失败的平台调用方法后,托管代码可以通过调用 GetLastWin32Error 方法检索错误代码。 由于错误代码可能会被其他托管类库方法的内部调用覆盖,因此应在平台调用方法调用后立即调用 GetLastError
或 GetLastWin32Error 方法。
当对平台调用方法的调用和对 GetLastWin32Error 的调用之间发生对以下托管成员的调用时,该规则将忽略这些调用。 这些成员不会更改错误代码,可用于确定某些平台调用方法调用是否成功。
如何解决冲突
若要解决此规则冲突,请移动对 GetLastWin32Error 的调用,以便它紧随对平台调用方法的调用之后。
何时禁止显示警告
如果平台调用方法调用与 GetLastWin32Error 方法调用之间的代码无法显式或隐式导致错误代码更改,可以安全地禁止显示此规则的警告。
示例
下面的示例演示了违反规则的方法和符合规则的方法。
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace InteroperabilityLibrary
{
internal class NativeMethods
{
private NativeMethods() {}
// Violates rule UseManagedEquivalentsOfWin32Api.
[DllImport("kernel32.dll", CharSet = CharSet.Auto,
SetLastError = true)]
internal static extern int ExpandEnvironmentStrings(
string lpSrc, StringBuilder lpDst, int nSize);
}
public class UseNativeMethod
{
string environmentVariable = "%TEMP%";
StringBuilder expandedVariable;
public void ViolateRule()
{
expandedVariable = new StringBuilder(100);
if(NativeMethods.ExpandEnvironmentStrings(
environmentVariable,
expandedVariable,
expandedVariable.Capacity) == 0)
{
// Violates rule CallGetLastErrorImmediatelyAfterPInvoke.
Console.Error.WriteLine(Marshal.GetLastWin32Error());
}
else
{
Console.WriteLine(expandedVariable);
}
}
public void SatisfyRule()
{
expandedVariable = new StringBuilder(100);
if(NativeMethods.ExpandEnvironmentStrings(
environmentVariable,
expandedVariable,
expandedVariable.Capacity) == 0)
{
// Satisfies rule CallGetLastErrorImmediatelyAfterPInvoke.
int lastError = Marshal.GetLastWin32Error();
Console.Error.WriteLine(lastError);
}
else
{
Console.WriteLine(expandedVariable);
}
}
}
}
相关规则
CA1060:将 P/Invoke 移动到 NativeMethods 类