telefonar GetLastError imediatamente após P/Invoke
TypeName |
CallGetLastErrorImmediatelyAfterPInvoke |
CheckId |
CA1404 |
Category (Categoria) |
Microsoft.interoperabilidade |
Quebrando alterar |
Não separável |
Causa
É feita uma telefonar para o Marshal.GetLastWin32Error método ou Win32 equivalente GetLastError função e a telefonar imediatamente anterior não é para um invocação de plataforma método.
Descrição da regra
Uma invocação de plataforma código não gerenciado do método acessos e é definido usando o Declare palavra-chave no Visual Basic ou o System.Runtime.InteropServices.DllImportAttribute atributo. Em geral, em caso de falha, não gerenciados funções telefonar o Win32 SetLastError função para conjunto um código de erro está associado com a falha. O chamador da função com 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 thread e será substituído pela próxima telefonar para SetLastError. Após uma telefonar 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 pelas chamadas internas de outros métodos de biblioteca de classes gerenciada, a GetLastError ou GetLastWin32Error método deve ser chamado imediatamente depois que invocação de plataforma chamadas de método.
A regra ignora chamadas para os seguintes membros gerenciado quando elas ocorrem entre a telefonar para invocação de plataforma o método e a telefonar para GetLastWin32Error. Esses membros não alteram o erro de código e são úteis para determinar o sucesso de alguns invocação de plataforma chamadas de método.
Como corrigir violações
Para corrigir uma violação dessa regra, mova a telefonar para GetLastWin32Error para que ela segue imediatamente a telefonar para invocação de plataforma o método.
Quando suprimir avisos
É seguro eliminar um aviso essa regra se o código entre invocação de plataforma chamadas de método e o GetLastWin32Error telefonar de método pode não explícita ou implicitamente causar alterar o código de erro.
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
Mover P/Invokes para classe NativeMethods
Pontos de entrada de P/Invoke devem existir
P/Invokes não deverá ser visível
Especifique o marshaling para argumentos de seqüência de caracteres de P/Invoke