CA1060

发布时间:2025-12-09 12:05:46 浏览次数:2

规则 ID

CA1060

类别

设计

修复是中断修复还是非中断修复

重大

原因

方法使用平台调用服务访问非托管代码,不是 NativeMethods 类之一的成员。

规则说明

平台调用方法(如使用 System.Runtime.InteropServices.DllImportAttribute 属性标记的方法)或在 Visual Basic 中使用 declare 关键字定义的方法可访问非托管代码。 这些方法应是处于以下一个类中:

NativeMethods - 此类不会对非托管代码权限取消堆栈审核。 (System.Security.SuppressUnmanagedCodeSecurityAttribute 不得应用于此类。)此类用于可在任何位置使用的方法,因为会执行堆栈审核。

SafeNativeMethods - 此类会对非托管代码权限取消堆栈审核。 (System.Security.SuppressUnmanagedCodeSecurityAttribute 应用于此类。)此类用于可供任何人安全调用的方法。 这些方法的调用方不需要执行完整安全评审以确保使用是安全的,因为这些方法对于任何调用方都无害。

UnsafeNativeMethods - 此类会对非托管代码权限取消堆栈审核。 (System.Security.SuppressUnmanagedCodeSecurityAttribute 应用于此类。)此类用于有潜在危险的方法。 这些方法的任何调用方都必须执行完整安全检查,以确保使用是安全的,因为不会执行任何堆栈审核。

这些类声明为 internal(在 Visual Basic 中为 Friend),并声明一个私有构造函数来阻止创建新实例。 这些类中的方法应是 static 和 internal(在在 Visual Basic 中是 Shared 和 Friend)。

如何解决冲突

若要解决与此规则的冲突,请将方法移动到合适的 NativeMethods 类中。 对于大多数应用程序,将 P/Invoke 移动到名为 NativeMethods 的新类便足够了。

但是,如果要开发在其他应用程序中使用的库,应考虑定义两个名为 SafeNativeMethods 和 UnsafeNativeMethods 的其他类。 这些类与 NativeMethods 类相似;但是,它们使用名为 SuppressUnmanagedCodeSecurityAttribute 的特殊属性进行标记 。 应用此属性时,运行时不会执行完整堆栈审核来确保所有调用方都具有 UnmanagedCode 权限。 运行时通常会在启动时检查是否具有此权限。 因此可极大地提高对这些非托管方法的调用的性能,还使具备有限权限的代码可以调用这些方法。

不过,应非常小心地使用此属性。 如果未正确实现,则可能会产生严重的安全隐患。

有关如何实现这些方法的信息,请参阅 NativeMethods 示例、SafeNativeMethods 示例和 UnsafeNativeMethods 示例 。

何时禁止显示警告

不禁止显示此规则发出的警告。

示例

下面的示例声明了违反此规则的方法。 若要更正该冲突,应将 RemoveDirectory P/Invoke 移动到设计为仅保存 P/invoke 的适当类。

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

NativeMethods 示例

由于 NativeMethods 类不应使用 SuppressUnmanagedCodeSecurityAttribute 进行标记,因此,置于其中的 P/invoke 需要 UnmanagedCode 权限 。 由于大多数应用程序从本地计算机运行并随完全信任一起运行,因此这通常不会成为问题。 但是,如果要开发可重用的库,则应考虑定义 SafeNativeMethods 或 UnsafeNativeMethods 类 。

下面的示例演示了一个 Interaction.Beep 方法,它可包装来自 user32.dll 的 MessageBeep 函数 。 MessageBeep P/Invoke 会置于 NativeMethods 类中 。

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 SubEnd ClassFriend 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 FunctionEnd Classpublic 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/Invoke 方法应置于名为 SafeNativeMethods 的类中。 不必要求获得权限,也不必过多注意从其处调用权限。

下面的示例演示了一个 Environment.TickCount 属性,它可包装来自 kernel32.dll 的 GetTickCount 函数 。

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 PropertyEnd 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 FunctionEnd Classpublic 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 示例

不能安全调用并且可能导致副作用的 P/Invoke 方法应置于名为 UnsafeNativeMethods 的类中。 应严格检查这些方法,以确保不会无意中向用户公开它们。 此外,这些方法在使用时,还应具有所需的其他权限,而不是 UnmanagedCode。

下面的示例演示了一个 Cursor.Hide 方法,它可包装来自 user32.dll 的 ShowCursor 函数 。

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 SubEnd 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 FunctionEnd Classpublic 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);}

另请参阅

设计规则

ca1060
需要做网站?需要网络推广?欢迎咨询客户经理 13272073477