Sdílet prostřednictvím


CA1060: Přesuňte volání nespravovaných kódů do třídy NativeMethods

TypeName

MovePInvokesToNativeMethodsClass

CheckId

CA1060

Kategorie

Microsoft.Design

Narušující změna

Narušující

Příčina

Metoda používá služby vyvolání platformy k přístupu k nespravovanému kódu a není členem jedné z tříd NativeMethods.

Popis pravidla

Metody vyvolání platformy, například ty, které jsou označeny pomocí atributu DllImportAttribute nebo metody, které jsou definovány pomocí použitím klíčového slova Declare v rámci Visual Basic, přistupují k nespravovanému kódu.Tyto metody by měly být v jedné z následujících tříd:

  • NativeMethods - Tato třída nepotlačuje krokování zásobníku pro oprávnění k nespravovanému kódu. (SuppressUnmanagedCodeSecurityAttribute nesmí být použito u této třídy.) Tato třída je pro metody, které lze použít kdekoli, protože zásobníku bude prováděno krokování zásobníku.

  • SafeNativeMethods - Tato třída potlačuje krokování zásobníku pro oprávnění k nespravovanému kódu. (SuppressUnmanagedCodeSecurityAttribute je použito u této třídy.) Tato třída je pro metody, které jsou bezpečné při každém volání.Volající těchto metod nejsou povinni provádět úplné přezkoumání zabezpečení pro ujištění, zda je použití zabezpečené, jelikož jsou metody neškodné pro všechny volající.

  • UnsafeNativeMethods - Tato třída potlačuje krokování zásobníku pro oprávnění k nespravovanému kódu. (SuppressUnmanagedCodeSecurityAttribute je použito u této třídy.) Tato třída je pro metody, které jsou potenciálně nebezpečné.Jakýkoliv volající těchto metod musí provést úplné přezkoumání zabezpečení pro ujištění, zda je použití zabezpečené, protože žádné krokování zásobníku nebude provedeno.

Tyto třídy jsou v jazyce Visual Basic deklarovány jako internal (Friend a deklarují privátní konstruktor pro zabránění vytváření nových instancí.Metody uvedené v těchto tříd by měly být static a internal (Shared a Friend v jazyce Visual Basic).

Jak vyřešit porušení

Pro vyřešení porušení tohoto pravidla odstranit, přesuňte metodu do příslušné třídy NativeMethods.Pro většinu aplikací je dostačující přesunutí do nové třídy s názvem NativeMethods.

Pokud však vyvíjíte knihovny pro použití v jiných aplikacích, zvažte definování dvou dalších tříd s názvem SafeNativeMethods a UnsafeNativeMethods.Tyto třídy se podobají třídě NativeMethods, avšak jsou označeny použitím speciálního atributu s názvem SuppressUnmanagedCodeSecurityAttribute.Při použití tohoto atributu neprovádí modul runtime úplné krokování zásobníku k ověření, zda mají všichni volající oprávnění UnmanagedCode.Modul runtime obvykle toto oprávnění zkontroluje při spuštění.Protože se kontrola neprovádí, může to znamenat značné zlepšení výkon pro volání těchto nespravovaných metod. Je také umožněno volání těchto metod kódem, který který má k volání minimální oprávnění.

Tento atribut by měl být však používán velmi opatrně.Pokud je nesprávně implementován může vést k závažným následkům při zabezpečení..

Informace o implementaci metod naleznete v příkladu NativeMethods, v příkladu SafeNativeMethods a v příkladu UnsafeNativeMethods.

Kdy potlačit upozornění

Nepotlačujte upozornění na toto pravidlo.

Příklad

Následující příklad deklaruje metodu, která toto pravidlo porušuje.Pro odstranění konfliktu by mělo být P/Invoke RemoveDirectory přesunuto do příslušné třídy, která je určena pro uložení pouze P/Invoke.

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

Příklad NativeMethods

Description

Protože by třída NativeMethods neměla být označena použitím P/Invoke SuppressUnmanagedCodeSecurityAttribute, které jsou v ni umístěny, bude zapotřebí oprávnění UnmanagedCode.Protože většina aplikací je spuštěna z místního počítače a je spuštěna s plnou důvěrou, nepředstavuje toto obvykle problém.Pokud však vyvíjíte opakovaně využitelné knihovny, zvažte definování třídy SafeNativeMethods nebo třídy UnsafeNativeMethods.

Následující příklad ukazuje metodu Interaction.Beep, která zabalí funkci MessageBeep z knihovny user32.dll.P/Invoke MessageBeep je vložen do třídy NativeMethods.

Kód

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

Příklad SafeNativeMethods

Description

Metody P/Invoke, které mohou být bezpečně vystaveny a nemají žádné vedlejší účinky by měly být umístěny do třídy s názvem SafeNativeMethods.Nemusíte požadovat oprávnění a nemusíte příliš věnovat pozornost odkud kam jsou volány.

Následující příklad ukazuje vlastnost Environment.TickCount, která zabalí funkci GetTickCount z knihovny kernel32.dll.

Kód

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

Příklad UnsafeNativeMethods

Description

Metody P/Invoke, které nelze bezpečně volat a které mohou způsobit vedlejší účinky by měly být umístěny do třídy s názvem UnsafeNativeMethods.Tyto metody by měly být důsledně kontrolovány pro ujištění, že nedojde k jejich neúmyslnému vystavení uživateli.S tím může pomoci pravidlo CA2118: Zkontrolujte použití SuppressUnmanagedCodeSecurityAttribute.Případně by měly metody mít jiné oprávnění, které bude při jejich použití požadováno místo UnmanagedCode.

Následující příklad ukazuje metodu Cursor.Hide, která zabalí funkci ShowCursor z knihovny user32.dll.

Kód

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

Viz také

Další zdroje

Upozornění návrhu