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 Tervez
A javítás kompatibilitástörő vagy nem törik Törés
Alapértelmezés szerint engedélyezve a .NET 9-ben 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.

  • SafeNativeMethods – 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 (internala Visual Basicben) deklarálva Friend 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 static (internal és Shared a Visual Basicben) kell lenniükFriend.

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 való használatra fejleszt kódtárakat, érdemes megfontolnia két másik osztály meghatározását, amelyeket SafeNativeMethodsnak é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 SafeNativeMethods 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 megfontolnia egy SafeNativeMethods vagy UnsafeNativeMethods osztály meghatározását.

Az alábbi példa egy Interaction.Beep metódust mutat be, amely a MessageBeep függvényt user32.dll. 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);
}

SafeNativeMethods 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 SafeNativeMethods 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 kernel32.dll.

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élda egy Cursor.Hide metódust mutat be , amely a ShowCursor függvényt user32.dll.

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

Lásd még