CA1404: вызывайте GetLastError сразу после P/Invoke
Товар | Значение |
---|---|
Идентификатор правила | CA1404 |
Категория | Microsoft.Interoperability |
Критическое изменение | Не критическое |
Причина
Вызов выполняется к System.Runtime.InteropServices.Marshal.GetLastWin32Error методу или эквивалентной функции Win32 GetLastError
, и вызов, который происходит непосредственно перед тем, не является методом вызова платформы.
Описание правила
Платформа вызывает метод доступа к неуправляемого кода и определяется с помощью Declare
ключевое слово в Visual Basic или атрибуте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/Invokes в класс NativeMethods
CA1400: необходимо наличие точек входа P/Invoke
CA1401: методы P/Invoke не должны быть видимыми
CA2101: укажите тип маршалинга для строковых аргументов P/Invoke
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по