Compartilhar via


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

Use o gerenciado equivalentes da API do Win32