Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ez a témakör bemutatja, hogyan érheti el a nem felügyelt függvényeket, és hogyan vezet be több attribútummezőt, amelyek a felügyelt kód metódusdefinícióját jegyzetelik. Példák a konstruktálásra. A platformhíváshoz használandó NET-alapú deklarációkat lásd: Adatok platformhívással történő rendezése.
Ahhoz, hogy egy felügyelt kódból elérhessen egy nem felügyelt DLL-függvényt, ismernie kell a függvény nevét és az azt exportáló DLL nevét. Ezzel az információval megkezdheti egy DLL-ben implementált nem felügyelt függvény felügyelt definíciójának megírását. Emellett beállíthatja, hogyan hívja meg a platform a függvényt, és hogyan alakítja az adatokat a függvénybe és onnan ki.
Megjegyzés:
A karakterláncot lefoglaló Windows API-függvények lehetővé teszik, hogy a karakterláncot egy módszer, például a LocalFree segítségével szabadítsa fel. A platformhívás eltérően kezeli az ilyen paramétereket. Platformhívások esetén a paramétert IntPtr típusúként kell megadni String típus helyett. A System.Runtime.InteropServices.Marshal osztály által biztosított metódusokkal manuálisan konvertálhatja és szabadíthatja fel a típust sztringgé.
A deklarálás alapjai
A nem felügyelt függvények felügyelt definíciói nyelvfüggőek, ahogy az alábbi példákban is látható. További teljes kód példákért lásd a platformhívási példákat.
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
Ha a DllImportAttribute.BestFitMapping, DllImportAttribute.CallingConvention, , DllImportAttribute.ExactSpellingDllImportAttribute.PreserveSig, DllImportAttribute.SetLastErrorvagy DllImportAttribute.ThrowOnUnmappableChar mezőket egy Visual Basic-deklarációra szeretné alkalmazni, az utasítás helyett az DllImportAttributeDeclare attribútumot kell használnia.
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);
A definíció módosítása
Akár explicit módon, akár nem állítja be őket, az attribútummezők a felügyelt kód viselkedését határozzák meg. A platformhívás a szerelvény metaadataiként létező különböző mezőkben beállított alapértelmezett értékek szerint működik. Ezt az alapértelmezett viselkedést egy vagy több mező értékének módosításával módosíthatja. Sok esetben az DllImportAttribute használatával állít be egy értéket.
Az alábbi táblázat a platformhíváshoz kapcsolódó attribútummezők teljes készletét sorolja fel. Minden mező esetében a tábla tartalmazza az alapértelmezett értéket, valamint egy hivatkozást, amely arra vonatkozó információt tartalmaz, hogy miként definiálhatók ezek a mezők a nem felügyelt DLL-függvények definiálásához.
| szakterület | Leírás |
|---|---|
| BestFitMapping | Engedélyezi vagy letiltja a legjobban illeszkedő leképezést. |
| CallingConvention | A metódusparaméterek átadásánál használt hívási konvenciót adja meg. Az alapértelmezett a WinAPI, amely megfelel a __stdcall értéknek a 32 bites Intel-alapú platformok esetén. |
| CharSet | Szabályozza a névtorzítást és a string argumentumoknak a függvényhez való átadásának módját. Az alapértelmezett érték a CharSet.Ansi. |
| EntryPoint | Megadja a meghívandó DLL-belépési pontot. |
| ExactSpelling | Azt határozza meg, hogy a belépési pontot a karakterkészletnek megfelelően kell-e módosítani. Az alapértelmezett érték programozási nyelvtől függően változik. |
| PreserveSig | Azt szabályozza, hogy a felügyelt metódus aláírása nem felügyelt aláírássá legyen-e alakítva, amely HRESULT értéket ad vissza, és a visszatérési értékhez további [out, retval] argumentumot tartalmaz. Az alapértelmezett érték true (az aláírást nem szabad átalakítani). |
| SetLastError | Lehetővé teszi a hívó számára, hogy az Marshal.GetLastWin32Error API-függvény használatával állapítsa meg, hogy hiba történt-e a metódus végrehajtása során. A Visual Basicben az alapértelmezett érték true; a C# és a C++, az alapértelmezett érték a false. |
| ThrowOnUnmappableChar | Ellenőrzi, hogy az ANSI "?" karakterré konvertált, nem leképezhető Unicode karakter esetén dobjon-e kivételt. |
Részletes referenciainformációkért lásd: DllImportAttribute.
Platformkérés biztonsági szempontok
Az Assert, Deny és PermitOnly tagjai a SecurityAction felsorolásban veremjárásmódosítóknak nevezzük. Ezek a tagok figyelmen kívül lesznek hagyva, ha deklaratív attribútumként használják őket a platformhívási deklarációkban és a COM Interface Definition Language (IDL) utasításokban.
Platformhívási példák
A jelen szakaszban szereplő minták meghívása RegistryPermission a platformon az attribútum használatát mutatja be a stack walk modifiers használatával.
Az alábbi példában a rendszer figyelmen kívül hagyja a SecurityActionAssert, Denyés PermitOnly a módosítókat.
[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();
A Demand következő példában szereplő módosító azonban elfogadott.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
SecurityAction a módosítók megfelelően működnek, ha egy olyan osztályba kerülnek, amely tartalmazza (burkolja) a platformhívás hívását.
[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 a módosítók megfelelően működnek a beágyazott forgatókönyvekben is, ahol a platformhívás kezdeményezőjére vannak helyezve:
{
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();
}
}
COM interop példák
Az ebben a szakaszban található COM-interop minták az attribútum használatát RegistryPermission szemléltetik a veremellenőrzési módosítókkal.
Az alábbi COM interop felületi deklarációk figyelmen kívül hagyják a Assert, Denyés PermitOnly módosítókat, hasonlóan az előző szakaszban szereplő platformhívási példákhoz.
[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();
}
Emellett a Demand módosító nem fogadható el a COM interop felületi deklarálási forgatókönyvekben, ahogy az az alábbi példában is látható.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDemandStubsItf
{
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallFileIoPermission();
}