Aracılığıyla paylaş


CA1060: P/Invokes öğesini NativeMethods sınıfına taşıyın

TypeName

MovePInvokesToNativeMethodsClass

CheckId

CA1060

Kategori

Microsoft.Tasarım

Bozan Değişiklik

Bozan

Sebep

Bir yöntem, yönetilmeyen koda erişmek için Platform Çağırma Hizmetlerini kullanır ve NativeMethods sınıflarından birinin üyesi değildir.

Kural Tanımlaması

DllImportAttribute özniteliğinde işaretlenenler gibi Platform Çağırma yöntemlerini veya Visual Basic içindeki Declare anahtar sözcüklerini kullanılarak nitelendirilen yöntemleri kullanarak yönetilmeyen koda erişir.Bu yöntemler aşağıdaki sınıflardan birinde olmalıdır:

  • NativeMethods -Bu sınıf yönetilmeyen kod izni için yığın yürümesi bastırmaz. (SuppressUnmanagedCodeSecurityAttribute bu sınıfa uygulanmamalıdır. Bu sınıf herhangi bir yerde kullanılabilen yöntemler içindir çünkü yığın adımı gerçekleşecektir.

  • SafeNativeMethods -Bu sınıf yönetilmeyen kod izni için yığın adımı bastırır. (SuppressUnmanagedCodeSecurityAttribute Bu sınıf için uygulanır.) Bu sınıf, herkes için çağırması güvenli yöntemler içindir.Bu yöntemleri çağıranların, kullanımın güvenli olduğundan emin olmak için tam güvenlik incelemesi gerçekleştirmesi gerekmez çünkü bunlar her çağıran için zararsızdır.

  • UnsafeNativeMethods -Bu sınıf yönetilmeyen kod izni için yığın adımı bastırır. (SuppressUnmanagedCodeSecurityAttribute Bu sınıf için uygulanır.) Bu sınıf, tehlike potansiyeli olan yöntemler içindir.Bu yöntemleri çağıranların, kullanımın güvenli olduğundan emin olmak için tam güvenlik incelemesi gerçekleştirmesi gerekir çünkü yığın adımı gerçekleştirilmez.

Bu sınıflar internal olarak bildirilir. (Visual Basic'de (Friend ) ve yeni örneklerin oluşturulmasını önlemek için özel bir oluşturucu bildirir.Bu sınıflardaki yöntemler static ve internal olmalıdır. (Visual Basic'te (Shared ve Friend )

İhlallerin Düzeltilmesi

Bu kural ihlalini düzeltmek için yöntemi uygun NativeMethods sınıfına taşıyın.Çoğu uygulama için, P/Invoke'ları NativeMethods isimli yeni bir sınıfa taşımak yeterlidir.

Ancak, eğer diğer uygulamalarda kullanmak için kitaplıklar geliştiriyorsanız, SafeNativeMethods ve UnsafeNativeMethods olarak adlandırılan başka iki sınıfı tanımlamayı düşünmelisiniz.Bu sınıflar NativeMethods sınıfına benzer; ancak, SuppressUnmanagedCodeSecurityAttribute isimli özel bir öznitelik kullanılarak işaretlenmişlerdir..Bu öznitelik uygulandığında, çalışma zamanı tüm arayanların UnmanagedCode iznine sahip olduğundan emin olmak için tam bir yığın yürüyüşü gerçekleştirmez.Başlangıç sırasında, çalışma zamanı bu izni düzenli olarak denetler.Denetim gerçekleştirilmediğinden, bu yönetilmeyen yöntemlere çağrılar için performansı büyük ölçüde artırabilir, ayrıca bu yöntemleri çağırmak için sınırlı izinleri olan kodları etkinleştirir.

Ancak, bu özniteliği oldukça dikkatli kullanmanız gerekir.Yanlış uygulanması, ciddi güvenlik sonuçları doğurabilir.

Yöntemlerin uygulanması hakkında daha fazla bilgi için bkz. NativeMethods Örneği, SafeNativeMethods Örneği, ve UnsafeNativeMethods Örneği.

Uyarılar Ne Zaman Bastırılmalı

Bu kuraldan bir uyarı gizlemeyin.

Örnek

Aşağıdaki örnek, bu kuralı ihlal eden bir yöntem bildirir.İhlali düzeltmek için RemoveDirectory P/Invoke, sadece P/Invoke'ları tutmak için tasarlanmış uygun bir sınıfa taşınmalıdır.

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

NativeMethods Örneği

Tanımlama

NativeMethods sınıfı SuppressUnmanagedCodeSecurityAttribute kullanılarak işaretlenmemesi gerektiğinden, içine konulan P/Invoke'lar UnmanagedCode iznine ihtiyaç duyarlar.Çoğu uygulamalar yerel bilgisayardan çalıştığından ve tam güven ile birlikte çalıştırıldığından, bu genellikle bir sorun teşkil etmez.Ancak, yeniden kullanılabilir kitaplıkları geliştiriyorsanız, bir SafeNativeMethods veya UnsafeNativeMethods sınıfı tanımlamayı düşünmelisiniz.

Aşağıdaki örnek user32.dll 'den MessageBeep fonksiyonunu saran Interaction.Beep yöntemini göstermektedir.MessageBeep P/Invoke'u NativeMethods sınıfına konur.

Code

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

SafeNativeMethods Örneği

Tanımlama

Herhangi bir yan etkileri olmayan ve güvenli bir şekilde herhangi bir uygulamaya maruz kalabilen P/Invoke yöntemleri SafeNativeMethods olarak adlandırılan bir sınıfa konmalıdır.İzin istemenize gerek yoktur ve nereden çağrıldıklarına dikkat etmeniz gerekmez.

Aşağıdaki örnek, kernel32.dll'den GetTickCount işlevini saran Environment.TickCount özelliğini gösterir.

Code

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

UnSafeNativeMethods Örneği

Tanımlama

Güvenle çağrılamayan ve yan etkilere neden olabilecek P/Invoke yöntemleri UnsafeNativeMethods adlı bir sınıfa koyulmalıdır.Bu yöntemler, kullanıcının istemediği durumlara maruz kalmadığından emin olmak için ciddi bir şekilde denetlenmelidir.CA2118: SuppressUnmanagedCodeSecurityAttribute kullanımını gözden geçir kuralı bu konuda yardımcı olabilir.Alternatif olarak, yöntemlerin UnmanagedCode yerine başka kullandıkları izinleri olabilir.

Aşağıdaki örnek, user32.dll'den ShowCursor işlevini saran Cursor.Hide yöntemini göstermektedir.

Code

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

Ayrıca bkz.

Diğer Kaynaklar

Tasarım Uyarıları