Поделиться через


CA2205: используйте управляемые эквиваленты API Win32

TypeName

UseManagedEquivalentsOfWin32Api

CheckId

CA2205

Категория

Microsoft.Usage

Критическое изменение

Не критическое

Причина

Определен метод вызова платформы, при этом в библиотеке классов .NET Framework существует метод с эквивалентной функциональностью.

Описание правила

Метод вызова платформы используется для вызова функций неуправляемых DLL-библиотек и определяется с помощью атрибута System.Runtime.InteropServices.DllImportAttribute или ключевого слова Declare в Visual Basic. Неверно определенный метод вызова платформы может привести к ошибкам во время выполнения из-за таких неполадок как неверно именованные функции, неправильное сопоставление типов данных параметров и возвращаемых значений, а также неверная спецификация полей (соглашение о вызове и набор символов). Как правило, вместо определения и прямого вызова неуправляемого метода более простым и надежным решением является вызов эквивалентного управляемого метода, если он доступен. Вызов метода вызова платформы также может привести к различным проблемам безопасности, которые придется решать.

Устранение нарушений

Чтобы исправить нарушение этого правила замените вызов неуправляемой функции вызовом ее управляемого эквивалента.

Отключение предупреждений

Предупреждения этого правила следует отключать, если предполагаемый для замены метод не обладает необходимой функциональностью.

Пример

В следующем примере показано определение метода вызова платформы, нарушающее это правило. Кроме того, показаны вызовы метода вызова платформы и эквивалентный управляемый метод.

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);
      }
   }
}

Связанные правила

CA1404: вызывайте GetLastError сразу после P/Invoke

CA1060: переместите P/Invokes в класс NativeMethods

CA1400: необходимо наличие точек входа P/Invoke

CA1401: методы P/Invoke не должны быть видимыми

CA2101: укажите тип маршалинга для строковых аргументов P/Invoke