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