CA1060:P/Invoke を NativeMethods クラスに移動しますCA1060: Move P/Invokes to NativeMethods class

TypeNameTypeName MovePInvokesToNativeMethodsClassMovePInvokesToNativeMethodsClass
CheckIdCheckId CA1060CA1060
カテゴリCategory Microsoft.DesignMicrosoft.Design
互換性に影響する変更点Breaking Change ありBreaking

原因Cause

メソッドは、プラットフォーム呼び出しサービスを使用してアンマネージコードにアクセスし、 NativeMethodsクラスのいずれのメンバーでもありません。A method uses Platform Invocation Services to access unmanaged code and is not a member of one of the NativeMethods classes.

規則の説明Rule description

System.Runtime.InteropServices.DllImportAttribute属性を使用してマークされている、またはのDeclare Visual BasicVisual Basicキーワードを使用して定義されているメソッドなどのプラットフォーム呼び出しメソッドは、アンマネージコードにアクセスします。Platform Invocation methods, such as those that are marked by using the System.Runtime.InteropServices.DllImportAttribute attribute, or methods that are defined by using the Declare keyword in Visual BasicVisual Basic, access unmanaged code. これらのメソッドは、次のいずれかのクラスに含まれている必要があります。These methods should be in one of the following classes:

  • NativeMethods -このクラスは、アンマネージコードのアクセス許可のスタックウォークを抑制しません。NativeMethods - This class does not suppress stack walks for unmanaged code permission. (System.Security.SuppressUnmanagedCodeSecurityAttributeこのクラスに適用することはできません)。このクラスは、スタックウォークが実行されるため、どこからでも使用できるメソッド用です。(System.Security.SuppressUnmanagedCodeSecurityAttribute must not be applied to this class.) This class is for methods that can be used anywhere because a stack walk will be performed.

  • SafeNativeMethods -このクラスは、アンマネージコードのアクセス許可のスタックウォークを抑制します。SafeNativeMethods - This class suppresses stack walks for unmanaged code permission. (System.Security.SuppressUnmanagedCodeSecurityAttributeは、このクラスに適用されます。)このクラスは、だれもが安全に呼び出すことができるメソッドを対象としています。(System.Security.SuppressUnmanagedCodeSecurityAttribute is applied to this class.) This class is for methods that are safe for anyone to call. これらのメソッドの呼び出し元は、メソッドがどの呼び出し元に対しても無害であるため、完全なセキュリティレビューを実行して、使用方法が安全であることを確認する必要はありません。Callers of these methods are not required to perform a full security review to make sure that the usage is secure because the methods are harmless for any caller.

  • UnsafeNativeMethods -このクラスは、アンマネージコードのアクセス許可のスタックウォークを抑制します。UnsafeNativeMethods - This class suppresses stack walks for unmanaged code permission. (System.Security.SuppressUnmanagedCodeSecurityAttributeは、このクラスに適用されます。)このクラスは、危険である可能性のあるメソッドを対象としています。(System.Security.SuppressUnmanagedCodeSecurityAttribute is applied to this class.) This class is for methods that are potentially dangerous. これらのメソッドの呼び出し元は、完全なセキュリティレビューを実行して、スタックウォークが実行されないため、使用状況が安全であることを確認する必要があります。Any caller of these methods must perform a full security review to make sure that the usage is secure because no stack walk will be performed.

これらのクラスは、 internal (FriendVisual Basic の) として宣言され、新しいインスタンスが作成されないようにするためのプライベートコンストラクターを宣言します。These classes are declared as internal (Friend, in Visual Basic) and declare a private constructor to prevent new instances from being created. これらのクラスのメソッドは、 staticinternal (Shared Friend Visual Basic) である必要があります。The methods in these classes should be static and internal (Shared and Friend in Visual Basic).

違反の修正方法How to fix violations

この規則違反を修正するには、メソッドを適切なNativeMethodsクラスに移動します。To fix a violation of this rule, move the method to the appropriate NativeMethods class. ほとんどのアプリケーションでは、P/Invoke をNativeMethodsという名前の新しいクラスに移動するだけで十分です。For most applications, moving P/Invokes to a new class that is named NativeMethods is enough.

ただし、他のアプリケーションで使用するためのライブラリを開発している場合は、 SafeNativeMethodsUnsafeNativeMethodsという2つのクラスを定義することを検討してください。However, if you are developing libraries for use in other applications, you should consider defining two other classes that are called SafeNativeMethods and UnsafeNativeMethods. これらのクラスは、 NativeMethodsクラスに似ています。ただし、これらはSuppressUnmanagedCodeSecurityAttributeという特殊な属性を使用してマークされます。These classes resemble the NativeMethods class; however, they are marked by using a special attribute called SuppressUnmanagedCodeSecurityAttribute. この属性が適用されると、ランタイムは完全なスタックウォークを実行せず、すべての呼び出し元にUnmanagedCodeアクセス許可があることを確認します。When this attribute is applied, the runtime does not perform a full stack walk to make sure that all callers have the UnmanagedCode permission. 通常、ランタイムは起動時にこのアクセス許可をチェックします。The runtime ordinarily checks for this permission at startup. このチェックは実行されないため、これらのアンマネージメソッドの呼び出しのパフォーマンスを大幅に向上させることができます。また、これらのメソッドを呼び出すためのアクセス許可が制限されているコードを有効にすることもできます。Because the check is not performed, it can greatly improve performance for calls to these unmanaged methods, It also enables code that has limited permissions to call these methods.

ただし、この属性は細心の注意を払って使用する必要があります。However, you should use this attribute with great care. 正しく実装されていない場合、セキュリティに深刻な影響を及ぼす可能性があります。「」をご覧ください。It can have serious security implications if it is implemented incorrectly..

メソッドの実装方法の詳細については、 NativeMethodsの例、 SafeNativeMethodsの例、およびUnsafeNativeMethodsの例を参照してください。For information about how to implement the methods, see the NativeMethods Example, SafeNativeMethods Example, and UnsafeNativeMethods Example.

警告を非表示にする場合When to suppress warnings

この規則による警告は抑制しないでください。Do not suppress a warning from this rule.

Example

次の例では、この規則に違反するメソッドを宣言しています。The following example declares a method that violates this rule. 違反を修正するには、 Removedirectory p/Invoke を、p/invoke のみを保持するように設計された適切なクラスに移動する必要があります。To correct the violation, the RemoveDirectory P/Invoke should be moved to an appropriate class that is designed to hold only P/Invokes.

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 の例NativeMethods Example

説明Description

NativeMethodsクラスはSuppressUnmanagedCodeSecurityAttributeを使用してマークされないようにする必要があるため、このクラスに格納されている P/invoke にはUnmanagedCodeアクセス許可が必要です。Because the NativeMethods class should not be marked by using SuppressUnmanagedCodeSecurityAttribute, P/Invokes that are put in it will require UnmanagedCode permission. ほとんどのアプリケーションはローカルコンピューターから実行され、完全信頼と共に実行されるため、通常は問題ではありません。Because most applications run from the local computer and run together with full trust, this is usually not a problem. ただし、再利用可能なライブラリを開発している場合は、 SafeNativeMethodsクラスまたはUnsafeNativeMethodsクラスを定義することを検討してください。However, if you are developing reusable libraries, you should consider defining a SafeNativeMethods or UnsafeNativeMethods class.

次の例は、user32.dll からmessagebeep関数をラップするビープ音のメソッドを示しています。The following example shows an Interaction.Beep method that wraps the MessageBeep function from user32.dll. Messagebeep P/Invoke はNativeMethodsクラスに格納されます。The MessageBeep P/Invoke is put in the NativeMethods class.

コードCode

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

SafeNativeMethods の例SafeNativeMethods Example

説明Description

P/Invoke メソッドは、任意のアプリケーションに安全に公開でき、副作用がない場合は、 SafeNativeMethodsという名前のクラスに配置する必要があります。P/Invoke methods that can be safely exposed to any application and that do not have any side effects should be put in a class that is named SafeNativeMethods. アクセス許可を要求する必要はなく、どこから呼び出されたかについての注意を払う必要はありません。You do not have to demand permissions and you do not have to pay much attention to where they are called from.

次の例は、kernel32.dll からGetTickCount関数をラップするTickCountプロパティを示しています。The following example shows an Environment.TickCount property that wraps the GetTickCount function from kernel32.dll.

コード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;  
         
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 の例UnsafeNativeMethods Example

説明Description

安全に呼び出すことができず、副作用を引き起こす可能性のある P/Invoke メソッドは、 UnsafeNativeMethodsという名前のクラスに配置する必要があります。P/Invoke methods that cannot be safely called and that could cause side effects should be put in a class that is named UnsafeNativeMethods. これらのメソッドは、意図せずにユーザーに公開されないように厳密にチェックする必要があります。These methods should be rigorously checked to make sure that they are not exposed to the user unintentionally. ルールCA2118:この問題を解決するには、SuppressUnmanagedCodeSecurityAttribute の使用状況を確認してください。The rule CA2118: Review SuppressUnmanagedCodeSecurityAttribute usage can help with this. また、メソッドには、使用時にUnmanagedCodeの代わりに要求される別のアクセス許可が必要です。Alternatively, the methods should have another permission that is demanded instead of UnmanagedCode when they use them.

次の例は、user32.dll からShowCursor関数をラップするHideメソッドを示しています。The following example shows a Cursor.Hide method that wraps the ShowCursor function from user32.dll.

コード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);   
}

関連項目See also