Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
| Propriedade | valor |
|---|---|
| ID da regra | CA1060 |
| Título | Mover P/Invokes para a classe NativeMethods |
| Categoria | Desenho |
| A correção causa interrupção ou não | Interrupção |
| Habilitado por padrão no .NET 10 | Não |
| Línguas aplicáveis | C# e Visual Basic |
Motivo
Um método usa Platform Invocation Services para acessar código não gerenciado e não é membro de uma das classes NativeMethods .
Descrição da regra
Métodos de invocação de plataforma, como aqueles que são marcados usando o atributo System.Runtime.InteropServices.DllImportAttribute, ou métodos que são definidos usando a palavra-chave Declare no Visual Basic, acessam código não gerido. Esses métodos devem estar em uma das seguintes classes:
NativeMethods - Esta classe não suprime percursos de pilha para permissão de código não gerido. System.Security.SuppressUnmanagedCodeSecurityAttribute( não deve ser aplicado a esta classe.) Esta classe é para métodos que podem ser usados em qualquer lugar porque uma caminhada de pilha será executada.
SafeNativeMethods - Esta classe suprime verificações de pilha para permissões de código não gerido. (System.Security.SuppressUnmanagedCodeSecurityAttribute é aplicado a esta classe.) Esta classe destina-se a métodos que podem ser chamados por qualquer pessoa com segurança. Os chamadores desses métodos não são obrigados a realizar uma revisão de segurança completa para garantir que o uso seja seguro, pois os métodos são inofensivos para qualquer chamador.
UnsafeNativeMethods - Esta classe suprime a análise do stack para permissões de código não gerido. System.Security.SuppressUnmanagedCodeSecurityAttribute( é aplicado a esta classe.) Esta classe é para métodos que são potencialmente perigosos. Qualquer chamador desses métodos deve executar uma revisão de segurança completa para certificar-se de que o uso é seguro, pois nenhum passeio de pilha será executado.
Essas classes são declaradas como internal (Friend no Visual Basic) e declaram um construtor privado para impedir que novas instâncias sejam criadas. Os métodos nessas classes devem ser static e internal (Shared e Friend no Visual Basic).
Como corrigir violações
Para corrigir uma violação dessa regra, mova o método para a classe NativeMethods apropriada. Para a maioria dos aplicativos, mover P/Invokes para uma nova classe chamada NativeMethods é suficiente.
No entanto, se você estiver desenvolvendo bibliotecas para uso em outros aplicativos, você deve considerar a definição de duas outras classes que são chamadas SafeNativeMethods e UnsafeNativeMethods. Essas classes se assemelham à classe NativeMethods , no entanto, elas são marcadas usando um atributo especial chamado SuppressUnmanagedCodeSecurityAttribute. Quando esse atributo é aplicado, o tempo de execução não executa uma verificação completa da pilha para garantir que todos os chamadores tenham a permissão UnmanagedCode. O tempo de execução normalmente verifica esta permissão na inicialização. Como a verificação não é executada, isso pode melhorar significativamente o desempenho das chamadas para esses métodos não gerenciados. Ele também permite que o código com permissões limitadas chame esses métodos.
No entanto, você deve usar esse atributo com muito cuidado. Pode ter sérias implicações de segurança se for implementado incorretamente.
Para obter informações sobre como implementar os métodos, consulte o exemplo NativeMethods, o exemplo SafeNativeMethods e o exemplo UnsafeNativeMethods.
Quando suprimir avisos
Não suprima um aviso desta regra.
Exemplo
O exemplo a seguir declara um método que viola essa regra. Para corrigir a violação, o RemoveDirectory P/Invoke deve ser movido para uma classe apropriada que é projetada para manter apenas P/Invokes.
' 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);
}
Exemplo de NativeMethods
Como a classe NativeMethods não deve ser marcada com o uso de SuppressUnmanagedCodeSecurityAttribute, as chamadas a P/Invokes nela exigirão a permissão UnmanagedCode. Como a maioria dos aplicativos é executada a partir do computador local e executada em conjunto com confiança total, isso geralmente não é um problema. No entanto, se você estiver desenvolvendo bibliotecas reutilizáveis, você deve considerar a definição de uma classe SafeNativeMethods ou UnsafeNativeMethods .
O exemplo a seguir mostra um método Interaction.Beep que encapsula a função MessageBeep de user32.dll. O MessageBeep P/Invoke é colocado na classe 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 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);
}
Exemplo de SafeNativeMethods
Os métodos P/Invoke que podem ser expostos com segurança a qualquer aplicação e que não têm quaisquer efeitos secundários devem ser colocados numa classe denominada SafeNativeMethods. Você não tem que prestar muita atenção para onde eles são chamados.
O exemplo a seguir mostra uma propriedade Environment.TickCount que encapsula a função GetTickCount de 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();
}
Exemplo de UnsafeNativeMethods
P/Invoke métodos que não podem ser chamados com segurança e que podem causar efeitos colaterais devem ser colocados em uma classe chamada UnsafeNativeMethods. Estes métodos devem ser rigorosamente verificados para garantir que não são expostos ao utilizador involuntariamente.
O exemplo a seguir mostra um método Cursor.Hide que encapsula a função ShowCursor de 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);
}