Compilación para OneCore
Al usar Visual Studio para compilar código en modo de usuario para Windows 10, puede personalizar las opciones del enlazador para versiones específicas de Windows. Tenga en cuenta los siguientes factores:
¿Debe ejecutarse el binario compilado solo en la versión más reciente de Windows? ¿O debería ejecutarse en versiones anteriores, como Windows 7?
¿El proyecto tiene dependencias de UWP?
Por ejemplo, al crear un nuevo proyecto de controlador UMDF v2, Visual Studio se vincula a OneCoreUAP.lib
de forma predeterminada. Esto da como resultado un binario que se ejecuta en la versión más reciente de Windows y permite la adición de la funcionalidad de UWP.
Sin embargo, en función de sus requisitos, puede optar por vincular a OneCore.lib
. En la tabla siguiente se muestran los escenarios aplicables a cada biblioteca:
Biblioteca | Escenario |
---|---|
OneCore.lib |
Todas las ediciones de Windows 7 y versiones posteriores, sin compatibilidad con UWP |
OneCoreUAP.lib |
Ediciones de Windows 7 y posteriores para UWP (Desktop, IoT, HoloLens, pero no Nano Server) de Windows 10 |
Nota:
Para cambiar las opciones del enlazador en Visual Studio, elija las propiedades del proyecto y vaya a Enlazador->Entrada->Dependencias adicionales.
Un subconjunto de API de Windows se compila bien, pero devuelve errores en tiempo de ejecución en ediciones OneCore que no son de escritorio (por ejemplo, Mobile o IoT).
Por ejemplo, la función InstallApplication devuelve ERROR_ NOT_SUPPORTED
en ediciones OneCore que no son de escritorio. La herramienta ApiValidator también notifica estos problemas. En la sección siguiente se describe cómo corregirlos.
Corrección de errores de ApiValidator mediante IsApiSetImplemented
Si el código llama a las API no universales, es posible que vea los siguientes errores de ApiValidator:
Error: <Binary Name> has unsupported API call to <Module Name><Api Name>
Si la aplicación o el controlador base deben ejecutarse en Windows 10, así como en versiones anteriores de Windows, debes quitar las llamadas API en la categoría anterior.
Error: <Binary Name> has a dependency on <Module Name><Api Name> but is missing: IsApiSetImplemented("<contract-name-for-Module>)
Las llamadas API de la categoría anterior se compilan correctamente, pero es posible que no se comporten según lo previsto en tiempo de ejecución, en función del sistema operativo de destino. Para pasar el requisito de capas de API para controladores de Windows, encapsule estas llamadas con IsApiSetImplemented.
Esto le permite compilar el código sin errores. A continuación, en tiempo de ejecución, si la máquina de destino no tiene la API necesaria, IsApiSetImplemented devuelve FALSE.
En el ejemplo de código siguiente se muestra cómo hacerlo.
Ejemplo de código: Uso directo de la API, sin evaluar la existencia
Este código funciona bien en versiones anteriores a Windows 10, pero cuando se ejecute en una edición OneCore de Windows 10 da como resultado un error WTSEnumerateSessions: 78 o ERROR_CALL_NOT_IMPLEMENTED 120 (0x78).
Este ejemplo de código produce un error en el requisito de capas de API de controladores de Windows con los siguientes errores de ApiValidator:
ApiValidation: Error: FlexLinkTest.exe has a dependency on 'wtsapi32.dll!WTSEnumerateSessionsW' but is missing: IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0")
ApiValidation: Error: FlexLinkTest.exe has a dependency on 'wtsapi32.dll!WTSFreeMemory' but is missing: IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0")
ApiValidation: NOT all binaries are Universal
Este es el código :
#include <windows.h>
#include <stdio.h>
#include <Wtsapi32.h>
int __cdecl wmain(int /* argc */, PCWSTR /* argv */ [])
{
PWTS_SESSION_INFO pInfo = {};
DWORD count = 0;
if (WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pInfo, &count))
{
wprintf(L"SessionCount = %d\n", count);
for (ULONG i = 0; i < count; i++)
{
PWTS_SESSION_INFO pCurInfo = &pInfo[i];
wprintf(L" %s: ID = %d, state = %d\n", pCurInfo->pWinStationName, pCurInfo->SessionId, pCurInfo->State);
}
WTSFreeMemory(pInfo);
}
else
{
wprintf(L"WTSEnumerateSessions failure : %x\n", GetLastError());
}
return 0;
}
Ejemplo de código: Uso directo de la API, después de evaluar la existencia
En este ejemplo se muestra cómo llamar a IsApiSetImplemented. En este ejemplo se pasa el requisito de capas de API de controladores de Windows con la siguiente salida de ApiValidator:
ApiValidation: All binaries are Universal
Este es el código :
#include <windows.h>
#include <stdio.h>
#include <Wtsapi32.h>
int __cdecl wmain(int /* argc */, PCWSTR /* argv */ [])
{
PWTS_SESSION_INFO pInfo = {};
DWORD count = 0;
if (!IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0"))
{
wprintf(L"IsApiSetImplemented on ext-ms-win-session-wtsapi32-l1-1-0 returns FALSE\n");
}
else
{
if (WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pInfo, &count))
{
wprintf(L"SessionCount = %d\n", count);
for (ULONG i = 0; i < count; i++)
{
PWTS_SESSION_INFO pCurInfo = &pInfo[i];
wprintf(L" %s: ID = %d, state = %d\n", pCurInfo->pWinStationName, pCurInfo->SessionId, pCurInfo->State);
}
WTSFreeMemory(pInfo);
}
else
{
wprintf(L"WTSEnumerateSessions failure : %x\n", GetLastError());
}
}
return 0;
}
Acciones recomendadas
- Revise las opciones del enlazador anteriores y actualice el proyecto de Visual Studio en consecuencia.
- Use la herramienta ApiValidator en el WDK. Esta herramienta se ejecuta automáticamente al compilar un controlador en Visual Studio.
- Use pruebas en tiempo de ejecución para comprobar que el código en modo de usuario se ejecuta según lo previsto en las ediciones OneCore que no son de escritorio. Tenga en cuenta que las API de código auxiliar pueden generar códigos de error diferentes.