Partilhar via


CA1060: Mover P/Invokes à classe NativeMethods

TypeName

MovePInvokesToNativeMethodsClass

CheckId

CA1060

Category (Categoria)

Microsoft.Design

Alteração Significativa

Interrompendo

Causa

Um método usa Serviços de Invocação de Plataforma para acessar código não gerenciado e não é um membro de uma das classes NativeMethods.

Descrição da Regra

Métodos de Invocação de Plataforma, tais como os marcados usando o atributo System.Runtime.InteropServices.DllImportAttribute, ou métodos definidos usando a palavra-chave Declare em Visual Basic acessam código não gerenciado.Esses métodos devem estar em uma das seguintes classes:

  • NativeMethods - esta classe não suprime movimentação da pilha para permissão de código não gerenciado.(System.Security.SuppressUnmanagedCodeSecurityAttribute não deve ser aplicado a esta classe.) Essa classe é para métodos que possam ser usados em qualquer lugar já que será feita uma movimentação de pilha.

  • SafeNativeMethods - essa classe suprime movimentação de pilha para permissão de código não gerenciado.(System.Security.SuppressUnmanagedCodeSecurityAttribute é aplicado a esta classe.) Essa classe é para métodos que são seguros para que qualquer um chame.Os chamadores de esses métodos não precisam fazer uma checagem de segurança completa para certificar-se de que o uso é seguro, já que, os métodos são inofensivos para qualquer chamador.

  • SafeNativeMethods - essa classe suprime movimentação de pilha para permissão de código não gerenciado.(System.Security.SuppressUnmanagedCodeSecurityAttribute é aplicado a esta classe.) Essa classe é para métodos potencialmente perigosos.Qualquer chamador destes métodos deve fazer uma checagem de segurança completa para certificar-se de que o uso é seguro uma vez que não haerá movimentação de pilha.

Essas classes são declaradas como internal (Friend, no Visual Basic) e declaram um construtor particular para impedir que novas instâncias sejam criadas.Os métodos nestas classes devem ser static e internal (Shared e Friend no Visual Basic).

Como Corrigir Violações

Para corrigir uma violação desta regra, mova o método para a classe apropriada de NativeMethods.Para a maioria dos aplicativos, mover P/Invokes para uma nova classe chamada de NativeMethods é suficiente.

No entanto, se você estiver desenvolvendo bibliotecas para uso em outros aplicativos, você deve considerar definir duas outras classes que chamadas de SafeNativeMethods e UnsafeNativeMethods.Essas classes são semelhantes à classe NativeMethods; no entanto, são marcadas usando um atributo especial chamado SuppressUnmanagedCodeSecurityAttribute.Quando esse atributo é aplicado, o runtime não faz uma movimentção completa de pilha para certificar-se de que todos os chamadores têm a permissão UnmanagedCode.O runtime normalmente verifica por esta permissão na inicialização.Uma vez que a verificação não é executada, é possível aumentar melhorar o desempenho para chamadas a estes métodos não gerenciados. Isso também habilita que código com permissões limitadas chame estes métodos.

Você deve, no entanto, usar este atributo com muito cuidado.Ele pode ter graves implicações na segurança se implementado incorretamente.

Para obter informações sobre como implementar métodos, consulte o exemplo NativeMethods, o exemplo SafeNativeMethods, e o exemplo UnsafeNativeMethods.

Quando Suprimir Alertas

Não elimine um alerta desta regra.

Exemplo

O exemplo a seguir declara um método que viola esta regra.Para corrigir a violação o RemoveDirectory P/Invoke deve ser movido para uma classe adequada que seja projetada para armazenar somente P/Invokes.

Imports System

NameSpace MSInternalLibrary

' Violates rule: MovePInvokesToNativeMethodsClass.
Friend Class UnmanagedApi
    Friend Declare Function RemoveDirectory Lib "kernel32" ( _
       ByVal Name As String) As Boolean
End Class

End NameSpace 
using System;
using System.Runtime.InteropServices;

namespace DesignLibrary
{
// Violates rule: MovePInvokesToNativeMethodsClass.
    internal class UnmanagedApi
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
        internal static extern bool RemoveDirectory(string name);
    }
}

Exemplo de NativeMethods

ms182161.collapse_all(pt-br,VS.110).gifDescrição

Uma vez que a classe NativeMethods não deve ser marcada usando P/Invokes SuppressUnmanagedCodeSecurityAttribute, que são colocado nela ela exigirá permissão UnmanagedCode.Uma vez que a maioria dos aplicativos são executados do computador local e rodam sob confiança total, isso geralmente não é um problema.No entanto, se você estiver desenvolvendo bibliotecas reutilizáveis, você deve considerar definir uma classe SafeNativeMethods ou UnsafeNativeMethods.

O exemplo a seguir mostra um método Interaction.Beep que envolve a função MessageBeep do user32.dll.O P/Invoke MessageBeep é colocado na classe NativeMethods.

ms182161.collapse_all(pt-br,VS.110).gifCódigo

Imports System    
Imports System.Runtime.InteropServices    
Imports System.ComponentModel         

Public NotInheritable Class Interaction  

    Private Sub New()        
    End Sub                

    ' Callers require Unmanaged permission        
    Public Shared Sub Beep()                        
        ' No need to demand a permission as callers of Interaction.Beep                     
        ' will require UnmanagedCode permission                     
        If Not NativeMethods.MessageBeep(-1) Then                
            Throw New Win32Exception()            
        End If

    End Sub  

End Class         

Friend NotInheritable Class NativeMethods  

    Private Sub New()        
    End Sub             

    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _        
    Friend Shared Function MessageBeep(ByVal uType As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean        
    End Function  

End Class
using System;    
using System.Runtime.InteropServices;    
using System.ComponentModel;              

public static class Interaction    
{        
    // Callers require Unmanaged permission        
    public static void Beep()           
    {            
        // No need to demand a permission as callers of Interaction.Beep            
        // will require UnmanagedCode permission            
        if (!NativeMethods.MessageBeep(-1))                
            throw new Win32Exception();        
    }    
}            

internal static class NativeMethods    
{        
    [DllImport("user32.dll", CharSet = CharSet.Auto)]        
    [return: MarshalAs(UnmanagedType.Bool)]        
    internal static extern bool MessageBeep(int uType);    
}

Exemplo de SafeNativeMethods

ms182161.collapse_all(pt-br,VS.110).gifDescrição

Os métodos de P/Invoke que podem ser expostos com segurança a qualquer aplicativo e que não têm nenhum efeito colateral devem ser colocados em uma classe chamada de SafeNativeMethods.Você precisa requerer permissões e você prestar muita atenção ao local de onde são chamados.

O exemplo a seguir mostra uma propriedade Environment.TickCount que envolve a função GetTickCount de kernel32.dll.

ms182161.collapse_all(pt-br,VS.110).gifCódigo

Imports System   
Imports System.Runtime.InteropServices   
Imports System.Security       

Public NotInheritable Class Environment       

    Private Sub New()       
    End Sub           

    ' Callers do not require Unmanaged permission       
    Public Shared ReadOnly Property TickCount() As Integer           
        Get               
            ' No need to demand a permission in place of               
            ' UnmanagedCode as GetTickCount is considered               
            ' a safe method               
            Return SafeNativeMethods.GetTickCount()               
        End Get       
    End Property       

End Class       

<SuppressUnmanagedCodeSecurityAttribute()> _   
Friend NotInheritable Class SafeNativeMethods             

    Private Sub New()       
    End Sub           

    <DllImport("kernel32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)> _       
    Friend Shared Function GetTickCount() As Integer       
    End Function       

End Class
using System;   
using System.Runtime.InteropServices;   
using System.Security;  

public static class Environment   
{       
    // Callers do not require UnmanagedCode permission       
    public static int TickCount        
    {           
        get           
        {              
            // No need to demand a permission in place of               
            // UnmanagedCode as GetTickCount is considered              
            // a safe method              
            return SafeNativeMethods.GetTickCount();           
        }       
    }   
}            

[SuppressUnmanagedCodeSecurityAttribute]   
internal static class SafeNativeMethods   
{       
    [DllImport("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]       
    internal static extern int GetTickCount();   
}

Exemplo de UnsafeNativeMethods

ms182161.collapse_all(pt-br,VS.110).gifDescrição

Os métodos de P/Invoke que não podem ser chamados com segurança e que podem causar efeitos colaterais devem ser colocados em uma classe chamada de UnsafeNativeMethods.Esses métodos devem rigorosamente checados para certificar-se que não sejam expostos ao usuário inadvertidamente.A regra CA2118: Uso de SuppressUnmanagedCodeSecurityAttribute de revisão pode ajudar com isso.Alternativamente, os métodos devem ter uma outra permissão que é demandada no lugar de UnmanagedCode quando eles os usam.

O exemplo a seguir mostra um método Cursor.Hide que envolve a função ShowCursor de user32.dll.

ms182161.collapse_all(pt-br,VS.110).gifCódigo

Imports System   
Imports System.Runtime.InteropServices   
Imports System.Security   
Imports System.Security.Permissions       

Public NotInheritable Class Cursor           

    Private Sub New()       
    End Sub           

    ' Callers do not require Unmanaged permission, however,         
    ' they do require UIPermission.AllWindows       
    Public Shared Sub Hide()                 
        ' Need to demand an appropriate permission                   
        ' in  place of UnmanagedCode permission as                    
        ' ShowCursor is not considered a safe method                   
        Dim permission As New UIPermission(UIPermissionWindow.AllWindows)           
        permission.Demand()           
        UnsafeNativeMethods.ShowCursor(False)                

    End Sub       

End Class       

<SuppressUnmanagedCodeSecurityAttribute()> _   
Friend NotInheritable Class UnsafeNativeMethods           

    Private Sub New()       
    End Sub           

    <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)> _       
    Friend Shared Function ShowCursor(<MarshalAs(UnmanagedType.Bool)> ByVal bShow As Boolean) As Integer       
    End Function       

End Class
using System;   
using System.Runtime.InteropServices;   
using System.Security;   
using System.Security.Permissions;           

public static class Cursor   
{       
    // Callers do not require UnmanagedCode permission, however,       
    // they do require UIPermissionWindow.AllWindows       
    public static void Hide()          
    {           
        // Need to demand an appropriate permission           
        // in  place of UnmanagedCode permission as            
        // ShowCursor is not considered a safe method           
        new UIPermission(UIPermissionWindow.AllWindows).Demand();           
        UnsafeNativeMethods.ShowCursor(false);       
    }   
}            

[SuppressUnmanagedCodeSecurityAttribute]   
internal static class UnsafeNativeMethods   
{       
    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]       
    internal static extern int ShowCursor([MarshalAs(UnmanagedType.Bool)]bool bShow);   
}

Consulte também

Outros recursos

Avisos de design