Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym temacie opisano sposób uzyskiwania dostępu do funkcji niezarządzanych i wprowadzono kilka pól atrybutów, które dodają adnotację do definicji metody w kodzie zarządzanym. Przykłady demonstrujące, jak konstruować deklaracje oparte na .NET, które mają być używane z wywołaniem platformy, zobacz Marshalling Data with Platform Invoke.
Aby uzyskać dostęp do niezarządzanej funkcji DLL z kodu zarządzanego, musisz znać nazwę funkcji i nazwę biblioteki DLL, która ją eksportuje. Dzięki tym informacjom można rozpocząć pisanie definicji zarządzanej dla niezarządzanej funkcji implementowanej w bibliotece DLL. Ponadto możesz dostosować sposób, w jaki platforma wywołuje funkcję oraz przetwarza dane do i z funkcji.
Uwaga / Notatka
Funkcje interfejsu API systemu Windows, które przydzielają ciąg, umożliwiają zwolnienie ciągu przy użyciu metody takiej jak LocalFree. Wywołanie platformy obsługuje takie parametry inaczej. W przypadku wywołań platformowych ustaw parametr jako typ IntPtr zamiast typu String. Użyj metod dostarczanych przez klasę System.Runtime.InteropServices.Marshal , aby przekonwertować typ na ciąg ręcznie i zwolnić go ręcznie.
Podstawy deklaracji
Definicje zarządzane do funkcji niezarządzanych są zależne od języka, jak widać w poniższych przykładach. Aby uzyskać więcej kompletnych przykładów kodu, zobacz Przykłady wywołań platformy.
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
Aby zastosować pola DllImportAttribute.BestFitMapping, DllImportAttribute.CallingConvention, DllImportAttribute.ExactSpelling, DllImportAttribute.PreserveSig, DllImportAttribute.SetLastError lub DllImportAttribute.ThrowOnUnmappableChar do deklaracji w Visual Basic, należy użyć atrybutu DllImportAttribute zamiast instrukcji 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);
Dostosowywanie definicji
Niezależnie od tego, czy ustawiasz je jawnie, czy nie, pola atrybutów pracują nad definiowaniem zachowania kodu zarządzanego. Wywołanie platformy działa zgodnie z wartościami domyślnymi ustawionymi na różnych polach, które istnieją jako metadane w zestawie. To zachowanie domyślne można zmienić, dostosowując wartości jednego lub większej liczby pól. W wielu przypadkach należy użyć elementu , DllImportAttribute aby ustawić wartość.
W poniższej tabeli wymieniono pełny zestaw pól atrybutów odnoszących się do wywołania platformy. Dla każdego pola tabela zawiera wartość domyślną i link do informacji na temat sposobu używania tych pól do definiowania niezarządzanych funkcji bibliotek DLL.
| (No changes needed) | Opis |
|---|---|
| BestFitMapping | Włącza lub wyłącza mapowanie najlepiej dopasowane. |
| CallingConvention | Określa konwencję wywoływania, która ma być używana w przekazywaniu argumentów metody. Wartość domyślna to WinAPI, która odpowiada __stdcall 32-bitowym platformom opartym na technologii Intel. |
| CharSet | Kontroluje zmiany nazw i sposób, w jaki argumenty tekstowe powinny być przekazywane do funkcji. Wartość domyślna to CharSet.Ansi. |
| EntryPoint | Określa punkt wejścia biblioteki DLL, który ma być wywoływany. |
| ExactSpelling | Określa, czy punkt wejścia powinien zostać zmodyfikowany tak, aby odpowiadał zestawowi znaków. Wartość domyślna zależy od języka programowania. |
| PreserveSig | Określa, czy sygnatura metody zarządzanej powinna zostać przekształcona w niezarządzany podpis, który zwraca wartość HRESULT i ma dodatkowy argument [out, retval] dla wartości zwracanej. Wartość domyślna to true (podpis nie powinien być przekształcany). |
| SetLastError | Umożliwia obiektowi wywołującemu używanie funkcji interfejsu Marshal.GetLastWin32Error API w celu określenia, czy wystąpił błąd podczas wykonywania metody. W języku Visual Basic wartość domyślna to true; w języku C# i C++wartość domyślna to false. |
| ThrowOnUnmappableChar | Kontroluje rzucanie wyjątku w przypadku nieodwzorowanego znaku Unicode, który jest konwertowany na znak ANSI „?”. |
Aby uzyskać szczegółowe informacje referencyjne, zobacz DllImportAttribute.
Zagadnienia dotyczące zabezpieczeń wywoływania platformy
Assert, Deny oraz PermitOnly członkowie wyliczenia SecurityAction są określani jako modyfikatory stosu. Te członki są ignorowane, jeśli są używane jako atrybuty deklaratywne w deklaracjach wywołujących platformę i instrukcjach IDL (Interface Definition Language COM).
Przykłady wywołań platformy
Przykłady wywołań na platformie w tej sekcji przedstawiają użycie atrybutu RegistryPermission z modyfikatorami stosu.
W poniższym przykładzie SecurityActionAssertmodyfikatory , Denyi PermitOnly są ignorowane.
[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();
Demand Jednak modyfikator w poniższym przykładzie jest akceptowany.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
SecurityAction Modyfikatory działają poprawnie, jeśli są umieszczane w klasie obejmującej wywołanie platformy.
[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 Modyfikatory działają również poprawnie w zagnieżdżonym scenariuszu, w którym są umieszczane na wywołującym platformowe wywołanie.
{
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();
}
}
Przykłady interoperacyjności COM
Przykłady interop COM w tej sekcji ilustrują użycie atrybutu RegistryPermission z modyfikatorami stosu.
Następujące deklaracje interfejsu międzyoperacyjności COM ignorują modyfikatory Assert, Deny, i PermitOnly, podobnie jak przykłady wywołania platformy w poprzedniej sekcji.
[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();
}
Ponadto, modyfikator Demand nie jest akceptowany w scenariuszach deklaracji interfejsu międzyoperacyjności COM, jak pokazano w poniższym przykładzie.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDemandStubsItf
{
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallFileIoPermission();
}