建置 OneCore
當您使用 Visual Studio 來建置 Windows 10 的使用者模式程式代碼時,您可以自定義連結器選項,以鎖定特定版本的 Windows。 請考慮下列因素:
建置的二進位檔應該只在最新版本的 Windows 上執行? 還是應該在舊版上執行,例如 Windows 7?
您的專案是否有任何 UWP 相依性?
例如,當您建立新的 UMDF v2 驅動程式專案時,Visual Studio 預設會連結至 OneCoreUAP.lib
。 這會導致在最新版本的 Windows 上執行的二進位檔,並允許新增 UWP 功能。
不過,視您的需求而定,您可以選擇改為連結至 OneCore.lib
。 下表顯示適用於每個連結庫的案例:
程式庫 | 案例 |
---|---|
OneCore.lib |
所有版本的 Windows 7 和更新版本,都不支援 UWP |
OneCoreUAP.lib |
Windows 7 和更新版本、UWP 版本 (Desktop、IoT、HoloLens,但不是 Nano Server) 的 Windows 10 |
注意
若要變更 Visual Studio 中的連結器選項,請選擇項目屬性,並流覽至 Linker-Input-Additional>> Dependencies。
Windows API 的子集會完全編譯,但在非桌面 OneCore 版本上傳回運行時錯誤(例如行動裝置版或 IoT)。
例如, InstallApplication 函式會在 ERROR_ NOT_SUPPORTED
非桌面 OneCore 版本上傳回。 ApiValidator 工具也會報告這些問題。 下一節說明如何修正它們。
使用 IsApiSetImplemented 修正 ApiValidator 錯誤
如果您的程式代碼呼叫非通用 API,您可能會看到下列 ApiValidator 錯誤:
Error: <Binary Name> has unsupported API call to <Module Name><Api Name>
如果您的應用程式或基底驅動程序必須在 Windows 10 和舊版 Windows 上執行,您必須移除上述類別中的 API 呼叫。
Error: <Binary Name> has a dependency on <Module Name><Api Name> but is missing: IsApiSetImplemented("<contract-name-for-Module>)
上述類別中的 API 呼叫會正常編譯,但可能不會如預期般在運行時間運作,視目標操作系統而定。 若要傳遞 Windows 驅動程式的 API 分層需求,請使用 IsApiSetImplemented 包裝這些呼叫。
這可讓您編譯程序代碼,且沒有任何錯誤。 然後在運行時間,如果目標計算機沒有所需的 API,IsApiSetImplemented 會傳回 FALSE。
下列程式代碼範例說明如何執行這項操作。
程序代碼範例:直接使用 API,而不評估是否存在
此程式代碼在 Windows 10 之前的 Windows 版本上正常執行,但在 Windows 10 的 OneCore 版本上執行程式代碼會導致 WTSEnumerateSessions 失敗:78 或 ERROR_CALL_NOT_IMPLEMENTED 120 (0x78)。
此程式代碼範例會失敗 Windows 驅動程式的 API 分層 需求,並出現下列 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
程式碼如下:
#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;
}
程式代碼範例:在評估是否存在之後,直接使用 API
此範例示範如何呼叫 IsApiSetImplemented。 此範例會使用下列 ApiValidator 輸出,傳遞 Windows 驅動程式的 API 分層需求:
ApiValidation: All binaries are Universal
程式碼如下:
#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;
}
建議動作
- 檢閱上述連結器選項,並據以更新您的Visual Studio專案。
- 在 WDK 中使用 ApiValidator 工具。 當您在 Visual Studio 中建置驅動程式時,此工具會自動執行。
- 使用運行時間測試來確認您的使用者模式程式代碼是否如預期般在非桌面 OneCore 版本上執行。 請注意,Stubbed API 可能會產生不同的錯誤碼。