Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In einigen Fällen kann ein bestimmter API-Satz-Vertragsname absichtlich einem leeren Modulnamen auf einigen Windows Geräten zugeordnet werden. Die Gründe hierfür variieren, aber ein häufiges Beispiel ist, dass ein teures Feature in Bezug auf Systemressourcen möglicherweise aus dem Windows Betriebssystem entfernt werden kann, wenn es für ein ressourceneinschränktes Gerät konfiguriert ist. Dies stellt eine Herausforderung für Anwendungen dar, optionale Features auf API-Ebene ordnungsgemäß zu behandeln.
Der herkömmliche Ansatz zum Testen, ob eine Win32-API verfügbar ist, besteht darin, LoadLibrary oder GetProcAddresszu verwenden. Dies ist jedoch kein zuverlässiges Mittel zum Testen von API-Sätzen aufgrund der Reverseweiterleitung. Wenn die Reverseweiterleitung auf eine bestimmte API angewendet wird, kann LoadLibrary oder GetProcAddress auch in Fällen, in denen die interne Implementierung entfernt wurde, zu einem gültigen Funktionszeiger aufgelöst werden. In diesem Fall zeigt der Funktionszeiger auf eine Stubfunktion, die einfach einen Fehler zurückgibt.
Um diesen Fall zu erkennen, können Sie die IsApiSetImplemented--Funktion verwenden, um die zugrunde liegende Verfügbarkeit einer bestimmten API-Implementierung abzufragen. Dieser Test meldet, ob der API-Satz im zusammengesetzten API-Satzschema auf dem ausgeführten Gerät vorhanden ist und ob er einem Implementierungsmodul zugeordnet ist.
Important
Eine erfolgreiche Verfügbarkeitsabfrage ist keine Garantie dafür, dass ein bestimmter Aufruf erfolgreich ausgeführt wird. Behandeln Sie weiterhin Modulladefehler, fehlende Exporte und die eigenen dokumentierten Fehlerergebnisse der API.
Im folgenden Codebeispiel wird veranschaulicht, wie IsApiSetImplemented verwendet wird, um zu bestimmen, ob der API-Satz, der WTSEnumerateSessionsW enthält, auf dem aktuellen Gerät verfügbar ist, bevor sie aufgerufen wird.
#include <windows.h>
#include <apiquery2.h>
#include <stdio.h>
#include <wtsapi32.h>
#pragma comment(lib, "OneCore.lib")
#pragma comment(lib, "Wtsapi32.lib")
int __cdecl wmain(int /* argc */, PCWSTR /* argv */ [])
{
PWTS_SESSION_INFOW pInfo = nullptr;
DWORD count = 0;
if (!IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0"))
{
wprintf(L"ext-ms-win-session-wtsapi32-l1-1-0 is not available.\n");
return 0;
}
if (WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pInfo, &count))
{
wprintf(L"SessionCount = %lu\n", count);
for (DWORD i = 0; i < count; i++)
{
PWTS_SESSION_INFOW pCurInfo = &pInfo[i];
wprintf(L" %ls: ID = %lu, state = %d\n", pCurInfo->pWinStationName,
pCurInfo->SessionId, static_cast<int>(pCurInfo->State));
}
WTSFreeMemory(pInfo);
}
else
{
wprintf(L"WTSEnumerateSessionsW failure: %lu\n", GetLastError());
}
return 0;
}
IsApiSetImplemented wird in "apiquery2.h" deklariert, und der normale öffentliche SDK-Linkpfad stellt ihn von OneCore.lib bereit. Diese Bibliothek ist von allen Importbibliotheken getrennt, die zum Aufrufen der optionalen Ziel-API selbst erforderlich sind.
Im obigen Beispiel wird wtsapi32.lib für einen statischen Import verknüpft, der das Beispiel kurz hält. Eine Produktionsanwendung, die ausgeführt werden muss, in der der API-Satz nicht vorhanden ist, sollte auch die Anleitung unter "Optionaler Codepfad erreichbar" anwenden.
Wählen Sie den Abfragenamen aus.
Übergeben Sie den Namen des API-Satzes, den Sie testen. API-Satznamen werden konventionell ohne .dll Suffix geschrieben, und die Beispiele auf dieser Seite verwenden dieses Formular. Das Suffix ist nicht Teil des API-Satznamens.
Informationen zum Ermitteln des zu übergebenden Namens finden Sie in der Tabelle "Anforderungen " auf der Referenzseite für die API, die Sie aufrufen möchten. Wenn diese Tabelle über eine API-Satzzeile verfügt, erhält sie den Vertragsnamen. Verwenden Sie andernfalls die DLL-Zeile , aber nur, wenn der Name selbst einen Vertragsnamen enthält, der mit api- oder ext-; ein physischer Modulname, z. B. Wtsapi32.dll , kein Vertrag ist und die Abfrage falsch zurückgibt.
Die Form des Namens hängt davon ab, wie die API adressiert wird.
| API-Oberfläche | Abfrageformular | Example |
|---|---|---|
| Benannte Gruppe | <contract>~<group> |
api-win-core-samplefeature~AdvancedOperations |
| Standardgruppe | Vertragsalias ohne ~Default |
api-win-core-samplefeature |
| Vertrag mit Versionsverwaltung | Vollständiger Versionsvertragsname | ext-ms-win-core-samplefeature-l1-1-0 |
Die samplefeature Namen sind illustrative Namen für eine fiktive Windows Komponente. Das Namenspräfix (api- oder ext-) spielt keine Rolle im Verfügbarkeitsverhalten.
Bei einer benannten Gruppe bedeutet eine erfolgreiche Abfrage, dass die Gruppe vorhanden ist, ihr Vertrag einem Implementierungsmodul zugeordnet ist, dass dieser Host in der aktuellen Ausführungsumgebung verwendet werden kann, die Gruppe nicht deaktiviert ist und alle der Gruppe zugeordneten Systemfeatures aktiviert sind. Eine Abfrage, die einen Vertragsalias verwendet, wendet die Vertrags- und Hostüberprüfungen an.
Wenn der öffentliche Header der API ein Is<APIName>Present Hilfsprogramm bereitstellt, bevorzugen Sie diesen Hilfsprogramm. Er enthält bereits den richtigen Namen für den API-Satz oder die Gruppe, der die API enthält.
Das Ergebnis einer Abfrage ist vertrags- oder gruppierend, nicht funktionsde granular. Zwei Hilfsprogramme, die von derselben benannten Gruppe unterstützt werden, geben immer dasselbe Ergebnis zurück, obwohl jedes Hilfsprogramm nach einer anderen API benannt ist.
Lassen Sie den optionalen Codepfad erreichbar.
Eine Verfügbarkeitsprüfung kann den Prozessstart nicht schützen, wenn die optionale API als statischer Import verknüpft ist. Das Ladeprogramm löst statische Importe vor dem Ausführen des Codes auf, sodass ein fehlendes Modul den Prozess fehlschlägt, bevor die Ausführung die Prüfung erreicht.
Verwenden Sie einen der folgenden Ansätze:
- Konfigurieren Sie das Modul, das die optionale API für das Verzögerte Laden enthält. Verzögertes Laden ist eine Linkereinstellung: angeben
/DELAYLOAD:<module>und verknüpfen delayimp.lib. Geben Sie den Modulnamen an, der in der Importtabelle Ihrer Binärdatei angezeigt wird. Dabei kann es sich um den klassischen DLL-Namen anstelle des API-Set-Vertragsnamens handeln. Für das vorangehende Beispiel ist dieser Name WTSAPI32.dll. - Oder lösen Sie das Ziel dynamisch mit LoadLibrary und GetProcAddress auf, nachdem die Verfügbarkeitsabfrage erfolgreich war.
Verwenden Sie LoadLibrary oder GetProcAddress nicht als Ersatz für die Verfügbarkeitsabfrage. Sie beantworten Modul- und Exportfragen, bewerten den benannten Gruppenstatus nicht und können wie zuvor beschrieben zu einem Reverseweiterleitungs-Stub aufgelöst werden. Verwenden Sie sie nach der Abfrage, um das separate Modul zu behandeln und Überprüfungen zu exportieren.
Verhalten in früheren Versionen von Windows
Die von OneCore.lib bereitgestellte Implementierung wählt zur Laufzeit einen verfügbaren Abfragemechanismus aus, sodass eine Anwendung, die IsApiSetImplemented aufruft , weiterhin auf einem System ausgeführt werden kann, das die zugrunde liegende Abfrageunterstützung vorausläuft.
Auf einem System, in dem kein Abfragemechanismus verfügbar ist:
- Ein gruppenqualifizierter Name, der FALSE enthält
~. Ein System, das benannte Gruppen nicht auswerten kann, kann nicht melden, dass eine Gruppe verfügbar ist. - Ein Name, der nicht mit einer Gruppe qualifiziert ist, kann WAHR zurückgeben. Dies behält die Kompatibilität mit Anwendungen bei, die ihre eigenen Weiterleitungs-DLLs für frühe Versionen von Windows bereitgestellt haben, wobei der Vertrag tatsächlich von diesem Weiterleitungsgeber erfüllt wurde.
Verwenden Sie keine API-Set-Verfügbarkeitsabfrage als Sicherheits- oder Autorisierungsprüfung.