CA1404: Chamar GetLastError imediatamente após P/Invoke.
TypeName |
CallGetLastErrorImmediatelyAfterPInvoke |
CheckId |
CA1404 |
<strong>Categoria</strong> |
Microsoft.Interoperability |
Alteração significativa |
Não-separável |
Causa
É feita uma chamada para o Marshal.GetLastWin32Error método ou Win32 equivalente GetLastError função e a chamada que vem imediatamente antes não é uma plataforma de invocação de método.
Descrição da regra
Uma plataforma chamar código não gerenciado do método acessos e é definida usando o Declare palavra-chave em Visual Basic ou System.Runtime.InteropServices.DllImportAttribute atributo. Geralmente, em caso de falha, funções não gerenciadas chamam Win32 SetLastError função para definir um código de erro está associado à falha. O chamador da função falha chama o Win32 GetLastError função para recuperar o código de erro e determinar a causa da falha. O código de erro é mantido em uma base por segmento e é substituído pela próxima chamada para SetLastError. Após uma chamada para uma plataforma com falha chamar o método, o código gerenciado pode recuperar o código de erro chamando o GetLastWin32Error método. Como o código de erro pode ser substituído por chamadas internas de outros métodos de biblioteca de classe gerenciada, o GetLastError ou GetLastWin32Error método deve ser chamado imediatamente após o invocação de plataforma chamada de método.
A regra ignora chamadas para os seguintes membros gerenciados quando elas ocorrem entre a chamada para a plataforma chamar o método e a chamada para GetLastWin32Error. Esses membros não alteram o erro e são úteis para determinar o sucesso de alguns plataforma chamar chamadas de método.
Como corrigir violações
Para corrigir uma violação desta regra, mova a chamada para GetLastWin32Error , de modo que ele imediatamente a chamada para a plataforma chamar o método.
Quando suprimir avisos
É seguro eliminar um aviso esta regra se o código entre a plataforma chamar chamadas de método e a GetLastWin32Error chamada de método não pode explicitamente ou implicitamente, fazer com que o código de erro ao alterar.
Exemplo
O exemplo a seguir mostra um método que viola a regra e um método que satisfaça a regra.
Imports System
Imports System.Runtime.InteropServices
Imports System.Text
Namespace InteroperabilityLibrary
Class NativeMethods
Private Sub New()
End Sub
' Violates rule UseManagedEquivalentsOfWin32Api.
Friend Declare Auto Function _
ExpandEnvironmentStrings Lib "kernel32.dll" _
(lpSrc As String, lpDst As StringBuilder, nSize As Integer) _
As Integer
End Class
Public Class UseNativeMethod
Dim environmentVariable As String = "%TEMP%"
Dim expandedVariable As StringBuilder
Sub 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)
End If
End Sub
Sub SatisfyRule()
expandedVariable = New StringBuilder(100)
If NativeMethods.ExpandEnvironmentStrings( _
environmentVariable, _
expandedVariable, _
expandedVariable.Capacity) = 0
' Satisfies rule CallGetLastErrorImmediatelyAfterPInvoke.
Dim lastError As Integer = Marshal.GetLastWin32Error()
Console.Error.WriteLine(lastError)
Else
Console.WriteLine(expandedVariable)
End If
End Sub
End Class
End Namespace
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);
}
}
}
}
Regras relacionadas
CA1060: Mover P/Invokes NativeMethods classe
CA1400: Os pontos de entrada de P/Invoke devem existir.
CA1401: P/Invokes não deverá ser visível
CA2101: Especifique o empacotamento para argumentos de seqüência de caracteres de P/Invoke.