Partilhar via


CA1060: mover P/Invokes para a classe NativeMethods

TypeName

MovePInvokesToNativeMethodsClass

CheckId

CA1060

Categoria

Microsoft.Design

Alteração Significativa

Quebra

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 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. (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. (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.

  • UnsafeNativeMethods - essa classe suprime movimentação de pilha para permissão de código não gerenciado. (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 haverá 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 movimentaçã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

Descriçã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.

Có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

Descriçã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.

Có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

Descriçã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: revisar uso de SuppressUnmanagedCodeSecurityAttribute 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.

Có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