Condividi tramite


CA2205: Utilizzare equivalenti gestiti dell'API Win32

TypeName

UseManagedEquivalentsOfWin32Api

CheckId

CA2205

Category

Microsoft.Usage

Breaking Change

Non sostanziale

Causa

Viene definito un metodo di platform invoke e nella libreria di classi .NET Framework è presente un metodo con la funzionalità equivalente.

Descrizione della regola

Un metodo di platform invoke viene utilizzato per chiamare una funzione DLL non gestita e viene definito mediante l'attributo System.Runtime.InteropServices.DllImportAttribute o la parola chiave Declare in Visual Basic. Un metodo di platform invoke definito in modo errato può causare eccezioni in fase di esecuzione come conseguenza di problemi quali funzione con nome non corretto, mapping errato dei tipi di dati di parametri e valori restituiti oppure specifiche di campi errate, ad esempio la convenzione di chiamata e il set di caratteri. Se disponibile, è in genere più semplice e presenta minori possibilità di errore chiamare il metodo gestito equivalente anziché definire e chiamare direttamente il metodo non gestito. La chiamata a un metodo di platform invoke può inoltre causare ulteriori problemi di sicurezza che dovranno essere risolti.

Come correggere le violazioni

Per correggere una violazione di questa regola, sostituire la chiamata alla funzione non gestita con una chiamata al relativo equivalente gestito.

Esclusione di avvisi

Escludere un avviso da questa regola se il metodo di sostituzione consigliato non fornisce la funzionalità desiderata.

Esempio

Nell'esempio riportato di seguito viene illustrata una definizione di metodo di platform invoke che viola la regola. Vengono inoltre illustrate le chiamate al metodo di platform invoke e al metodo gestito equivalente.

Imports System
Imports System.Runtime.InteropServices
Imports System.Text

Namespace UsageLibrary

   Class NativeMethods

      Private Sub New()
      End Sub

      ' The following method definitions violate the rule.

      <DllImport("kernel32.dll", CharSet := CharSet.Unicode, _ 
         SetLastError := True)> _ 
      Friend Shared Function ExpandEnvironmentStrings _ 
         (lpSrc As String, lpDst As StringBuilder, nSize As Integer) _ 
         As Integer
      End Function

      Friend Declare Unicode Function ExpandEnvironmentStrings2 _ 
         Lib "kernel32.dll" Alias "ExpandEnvironmentStrings" _ 
         (lpSrc As String, lpDst As StringBuilder, nSize As Integer) _ 
         As Integer

   End Class

   Public Class UseNativeMethod

      Shared Sub Main()

         Dim environmentVariable As String = "%TEMP%"
         Dim expandedVariable As New StringBuilder(100)

         ' Call the unmanaged method.
         NativeMethods.ExpandEnvironmentStrings( _ 
            environmentVariable, _ 
            expandedVariable, _ 
            expandedVariable.Capacity)

         ' Call the unmanaged method.
         NativeMethods.ExpandEnvironmentStrings2( _ 
            environmentVariable, _ 
            expandedVariable, _ 
            expandedVariable.Capacity)

         ' Call the equivalent managed method.
         Environment.ExpandEnvironmentVariables(environmentVariable)

      End Sub

   End Class

End Namespace
using System;
using System.Runtime.InteropServices;
using System.Text;

namespace UsageLibrary
{
   internal class NativeMethods
   {
      private NativeMethods() {}

      // The following method definition violates the rule.
      [DllImport("kernel32.dll", CharSet = CharSet.Unicode, 
          SetLastError = true)]
      internal static extern int ExpandEnvironmentStrings(
         string lpSrc, StringBuilder lpDst, int nSize);
   }

   public class UseNativeMethod
   {
      public void Test()
      {
         string environmentVariable = "%TEMP%";
         StringBuilder expandedVariable = new StringBuilder(100);

         // Call the unmanaged method.
         NativeMethods.ExpandEnvironmentStrings(
            environmentVariable, 
            expandedVariable, 
            expandedVariable.Capacity);

         // Call the equivalent managed method.
         Environment.ExpandEnvironmentVariables(environmentVariable);
      }
   }
}

Regole correlate

CA1404: Chiamare GetLastError immediatamente dopo P/Invoke

CA1060: Spostare i P/Invoke nella classe NativeMethods

CA1400: I punti di ingresso P/Invoke devono esistere

CA1401: I P/Invoke non devono essere visibili

CA2101: Specificare il marshalling per gli argomenti di stringa P/Invoke