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.
Este tópico descreve como acessar funções não gerenciadas e apresenta vários campos de atributo que anotam a definição de método no código gerenciado. Para exemplos que demonstram como construir declarações baseadas em .NET para serem usadas com invocação de plataforma, consulte Marshalling Data with Platform Invoke.
Antes de poder acessar uma função DLL não gerenciada a partir do código gerenciado, você precisa saber o nome da função e o nome da DLL que a exporta. Com essas informações, você pode começar a escrever a definição gerenciada para uma função não gerenciada que é implementada em uma DLL. Além disso, você pode ajustar a maneira como a plataforma invoca a função e transmite os dados de e para a função.
Observação
As funções da API do Windows que alocam uma cadeia de caracteres permitem que você libere a cadeia de caracteres usando um método como LocalFree
. A invocação de plataforma lida com esses parâmetros de forma diferente. Para chamadas de invocação de plataforma, faça o parâmetro ser do tipo IntPtr
em vez do tipo String
. Use métodos fornecidos pela System.Runtime.InteropServices.Marshal classe para converter o tipo em uma cadeia de caracteres manualmente e liberá-la manualmente.
Noções básicas da declaração
As definições gerenciadas para funções não gerenciadas dependem do idioma, como você pode ver nos exemplos a seguir. Para obter exemplos de código mais completos, consulte Exemplos de invocação de plataforma.
Friend Class NativeMethods
Friend Declare Auto Function MessageBox Lib "user32.dll" (
ByVal hWnd As IntPtr,
ByVal lpText As String,
ByVal lpCaption As String,
ByVal uType As UInteger) As Integer
End Class
Para aplicar os campos DllImportAttribute.BestFitMapping, DllImportAttribute.CallingConvention, DllImportAttribute.ExactSpelling, DllImportAttribute.PreserveSig, DllImportAttribute.SetLastError ou DllImportAttribute.ThrowOnUnmappableChar a uma declaração do Visual Basic, deve-se usar o atributo DllImportAttribute em vez da instrução Declare
.
Imports System.Runtime.InteropServices
Friend Class NativeMethods
<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Friend Shared Function MessageBox(
ByVal hWnd As IntPtr,
ByVal lpText As String,
ByVal lpCaption As String,
ByVal uType As UInteger) As Integer
End Function
End Class
using System;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
[DllImport("user32.dll")]
internal static extern int MessageBox(
IntPtr hWnd, string lpText, string lpCaption, uint uType);
}
using namespace System;
using namespace System::Runtime::InteropServices;
[DllImport("user32.dll")]
extern "C" int MessageBox(
IntPtr hWnd, String* lpText, String* lpCaption, unsigned int uType);
Ajustando a definição
Quer você os defina explicitamente ou não, os campos de atributo estão em ação definindo o comportamento do código gerenciado. A invocação de plataforma opera conforme os valores padrão definidos em vários campos que existem como metadados em uma assembly. Você pode alterar esse comportamento padrão ajustando os valores de um ou mais campos. Em muitos casos, você usa o DllImportAttribute para definir um valor.
A tabela a seguir lista o conjunto completo de campos de atributo que pertencem à invocação de plataforma. Para cada campo, a tabela inclui o valor padrão e um link para informações sobre como usar esses campos para definir funções DLL não gerenciadas.
Campo | Descrição |
---|---|
BestFitMapping | Habilita ou desabilita o mapeamento mais adequado. |
CallingConvention | Especifica a convenção de chamada a ser usada na passagem de argumentos de método. O padrão é WinAPI , que corresponde a __stdcall nas plataformas Intel de 32 bits. |
CharSet | Controla a obfuscação de nomes e a maneira como os argumentos de cadeia de caracteres devem ser transformados para a função. A predefinição é CharSet.Ansi . |
EntryPoint | Especifica o ponto de entrada da DLL a ser chamado. |
ExactSpelling | Controla se um ponto de entrada deve ser modificado para corresponder ao conjunto de caracteres. O valor padrão varia de acordo com a linguagem de programação. |
PreserveSig | Controla se a assinatura do método gerido deve ser transformada numa assinatura não-gerida que retorna um HRESULT e tem um argumento adicional [out, retval] para o valor retornado. O padrão é true (a assinatura não deve ser transformada). |
SetLastError | Permite que o chamador use a Marshal.GetLastWin32Error função API para determinar se ocorreu um erro durante a execução do método. No Visual Basic, o padrão é true ; em C# e C++, o padrão é false . |
ThrowOnUnmappableChar | Controla o lançamento de uma exceção em um caractere Unicode não mapeável que é convertido em um caractere ANSI "?" |
Para obter informações de referência detalhadas, consulte DllImportAttribute.
A plataforma invoca considerações de segurança
Os membros Assert
, Deny
e PermitOnly
da enumeração SecurityAction são referidos como modificadores de percurso na pilha . Esses membros serão ignorados se forem usados como atributos declarativos em declarações de invocação de plataforma e instruções IDL (COM Interface Definition Language).
Exemplos de invocação de plataforma
Os exemplos de invocação de plataforma nesta seção ilustram o RegistryPermission
uso do atributo com os modificadores de caminhada de pilha.
No exemplo a seguir, os SecurityActionAssert
modificadores , Deny
e PermitOnly
são ignorados.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
private static extern bool CallRegistryPermissionAssert();
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Deny, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.PermitOnly, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
No entanto, o Demand
modificador no exemplo a seguir é aceito.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
SecurityAction Os modificadores funcionam corretamente se forem colocados em uma classe que contém (encapsula) a chamada de invocação de plataforma.
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
public ref class PInvokeWrapper
{
public:
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionDeny();
};
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
class PInvokeWrapper
{
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionDeny();
}
SecurityAction Os modificadores também funcionam corretamente em um cenário aninhado onde são colocados no chamador da chamada de invocação da plataforma:
{
public ref class PInvokeWrapper
public:
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionDeny();
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
public static bool CallRegistryPermission()
{
return CallRegistryPermissionInternal();
}
};
class PInvokeScenario
{
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionInternal();
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
public static bool CallRegistryPermission()
{
return CallRegistryPermissionInternal();
}
}
Exemplos de interoperabilidade COM
Os exemplos de interoperabilidade COM nesta seção ilustram o uso do atributo RegistryPermission
com os modificadores de percurso de pilha.
As seguintes declarações de interface de interoperabilidade COM ignoram os modificadores Assert
, Deny
, e PermitOnly
semelhante aos exemplos de invocação de plataforma na seção anterior.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IAssertStubsItf
{
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Assert, Unrestricted = true)]
bool CallFileIoPermission();
}
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDenyStubsItf
{
[RegistryPermission(SecurityAction.Deny, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Deny, Unrestricted = true)]
bool CallFileIoPermission();
}
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IAssertStubsItf
{
[RegistryPermission(SecurityAction.PermitOnly, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.PermitOnly, Unrestricted = true)]
bool CallFileIoPermission();
}
Além disso, o Demand
modificador não é aceito em cenários de declaração de interface de interoperabilidade COM, conforme mostrado no exemplo a seguir.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDemandStubsItf
{
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallFileIoPermission();
}
Ver também
- Consumindo funções DLL não gerenciadas
- Especificando um ponto de entrada
- Especificando um conjunto de caracteres
- Exemplos de invocação de plataforma
- Considerações de segurança relacionadas à invocação de plataforma
- Identificando funções em DLLs
- Criando uma classe para manter funções DLL
- Chamando uma função DLL