Megosztás a következőn keresztül:


CA1060: P/Invokes áthelyezése NativeMethods osztályba

Tulajdonság Érték
Szabályazonosító CA1060
Cím P/Invokes áthelyezése NativeMethods osztályba
Kategória Design
A javítás kompatibilitástörő vagy nem törik Törés
Alapértelmezés szerint engedélyezve a .NET 8-ban Nem

Ok

A metódus a Platform Invocation Services használatával fér hozzá a nem felügyelt kódhoz, és nem tagja a NativeMethods-osztályok egyikének.

Szabály leírása

A platformhívási metódusok, például az attribútummal System.Runtime.InteropServices.DllImportAttribute megjelöltek, vagy a Visual Basicben a Declare kulcsszóval definiált metódusok nem felügyelt kódhoz férnek hozzá. Ezeknek a módszereknek az alábbi osztályok egyikében kell lenniük:

  • NativeMethods – Ez az osztály nem tiltja le a nem felügyelt kódengedélyek verembevezetéseit. (System.Security.SuppressUnmanagedCodeSecurityAttribute erre az osztályra nem alkalmazható.) Ez az osztály olyan metódusokhoz készült, amelyek bárhol használhatók, mert verembejárást hajtanak végre.

  • Széf NativeMethods – Ez az osztály letiltja a nem felügyelt kódengedélyek verembevezetését. (System.Security.SuppressUnmanagedCodeSecurityAttribute erre az osztályra vonatkozik.) Ez az osztály olyan metódusokhoz készült, amelyek bárki számára biztonságosak. Ezeknek a metódusoknak a hívóinak nem kell teljes körű biztonsági felülvizsgálatot végezniük, hogy meggyőződjenek arról, hogy a használat biztonságos, mert a metódusok ártalmatlanok a hívók számára.

  • Nem biztonságosNativeMethods – Ez az osztály letiltja a nem felügyelt kódengedélyek verembevezetését. (System.Security.SuppressUnmanagedCodeSecurityAttribute erre az osztályra vonatkozik.) Ez az osztály olyan metódusokhoz készült, amelyek potenciálisan veszélyesek. Ezeknek a metódusoknak a hívóinak teljes biztonsági felülvizsgálatot kell végezniük annak érdekében, hogy a használat biztonságos legyen, mert nem történik verembejárás.

Ezek az osztályok (Frienda Visual Basicben) deklarálva internal vannak, és deklarálnak egy magánkonstruktort, hogy megakadályozzák az új példányok létrehozását. Ezekben az osztályokban a metódusoknak és internal (Shared és Friend a Visual Basicben) kell lenniükstatic.

Szabálysértések kijavítása

A szabály megsértésének kijavításához helyezze át a metódust a megfelelő NativeMethods osztályba. A legtöbb alkalmazás esetében elegendő a P/Invokes áthelyezése egy NativeMethods nevű új osztályba.

Ha azonban más alkalmazásokban használható kódtárakat fejleszt, érdemes megfontolnia két másik osztály meghatározását, amelyeket Széf NativeMethodsnak és UnsafeNativeMethodsnak nevezünk. Ezek az osztályok hasonlítanak a NativeMethods osztályra, de a rendszer a SuppressUnmanagedCodeSecurityAttribute nevű speciális attribútummal jelöli őket. Az attribútum alkalmazásakor a futtatókörnyezet nem hajt végre teljes verembeli sétát, hogy minden hívó rendelkezzen unmanagedCode engedéllyel. A futtatókörnyezet általában ezt az engedélyt ellenőrzi indításkor. Mivel az ellenőrzés nem történik meg, jelentősen javíthatja az ilyen nem felügyelt metódusokra irányuló hívások teljesítményét. Emellett engedélyezi a korlátozott engedélyekkel rendelkező kódokat is ezeknek a metódusoknak a meghívásához.

Ezt az attribútumot azonban nagy körültekintéssel kell használnia. Súlyos biztonsági következményekkel járhat, ha helytelenül implementálják.

A metódusok implementálásával kapcsolatos információkért lásd a NativeMethods példát, a Széf NativeMethods példát és a NemsafeNativeMethods példát.

Mikor kell letiltani a figyelmeztetéseket?

Ne tiltsa el a szabály figyelmeztetését.

Példa

Az alábbi példa egy olyan metódust deklarál, amely megsérti ezt a szabályt. A szabálysértés kijavításához a RemoveDirectory P/Invoke parancsot át kell helyezni egy olyan megfelelő osztályba, amely csak P/Invokes tárolására lett kialakítva.

' Violates rule: MovePInvokesToNativeMethodsClass.
Friend Class UnmanagedApi
    Friend Declare Function RemoveDirectory Lib "kernel32" (
   ByVal Name As String) As Boolean
End Class
// Violates rule: MovePInvokesToNativeMethodsClass.
internal class UnmanagedApi
{
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    internal static extern bool RemoveDirectory(string name);
}

NativeMethods példa

Mivel a NativeMethods osztályt nem szabad a SuppressUnmanagedCodeSecurityAttribute használatával megjelölni, a benne lévő P/Invokes nem felügyelt kód engedélyre lesz szükség. Mivel a legtöbb alkalmazás a helyi számítógépről fut, és teljes megbízhatósággal együtt fut, ez általában nem jelent problémát. Ha azonban újrafelhasználható kódtárakat fejleszt, érdemes lehet definiálni egy Széf NativeMethods vagy UnsafeNativeMethods osztályt.

Az alábbi példa egy Interaction.Beep metódust mutat be, amely a MessageBeep függvényt a user32.dll fájlból burkolja. A MessageBeep P/Invoke a NativeMethods osztályba kerül.

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

Széf NativeMethods példa

A P/Invoke metódusokat, amelyek biztonságosan ki lehetnek téve bármely alkalmazásnak, és amelyek nem rendelkeznek semmilyen mellékhatással, egy Széf NativeMethods nevű osztályba kell helyezni. Nem kell különösebb figyelmet fordítania arra, hogy honnan hívják őket.

Az alábbi példa egy Environment.TickCount tulajdonságot mutat be, amely a GetTickCount függvényt a kernel32.dll fájlból burkolja.

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

NemsafeNativeMethods példa

A nem biztonságosan meghívható és mellékhatásokat okozó P/Invoke metódusokat a Nem biztonságosNativeMethods nevű osztályba kell helyezni. Ezeket a módszereket szigorúan ellenőrizni kell, hogy véletlenül ne legyenek kitéve a felhasználónak.

Az alábbi példában egy Cursor.Hide metódus látható, amely a ShowCursor függvényt a user32.dll fájlból tördeli.

Public NotInheritable Class Cursor

    Private Sub New()
    End Sub

    Public Shared Sub Hide()
        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
public static class Cursor
{
    public static void Hide()
    {
        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);
}

Kapcsolódó információk