PAYATHON 2026

WIN10 +VS2017调用zolozVerify后摄像头显示白屏

支付小周

结论

摄像头本身大概率没有故障。官方程序包中的 testmain.exe 可以正常显示画面,说明摄像头、驱动和 SDK 的基本采集功能都能正常工作。

白屏更可能是业务程序的集成环境与 testmain.exe 不一致。建议重点检查以下几项:

  1. SDK 依赖的 DLL、模型或资源文件没有完整部署。
  2. 程序的工作目录不正确,导致 SDK 无法通过相对路径加载资源。
  3. 工程平台与 SDK 位数不一致,例如程序是 x64,而 SDK 是 x86。
  4. Debug/Release 运行库或 Visual C++ Runtime 不匹配。
  5. zolozVerify 没有在 SDK 要求的线程或消息循环环境中调用。
  6. 显卡驱动、远程桌面或硬件加速导致预览窗口渲染失败。

优先检查运行目录

不要只把 SDK 的几个 DLL 复制到业务程序目录。可以先让业务程序在与 testmain.exe 完全相同的目录结构中运行,保留程序包中的 DLL、配置文件、模型文件、图片和其他资源目录。

需要特别注意的是,Visual Studio 启动程序时,当前工作目录不一定是 EXE 所在目录。如果 SDK 内部通过相对路径读取文件,就可能出现窗口已经打开、摄像头也完成初始化,但预览区域无法正常渲染的情况。

可以先在项目属性中设置:

配置属性
  → 调试
  → 工作目录
  → $(TargetDir)

也可以在初始化 SDK 前,将当前目录切换到 EXE 所在目录:

#include <Windows.h>
#include <string>

static bool SetWorkingDirectoryToExePath()
{
    wchar_t exePath[MAX_PATH] = {};
    DWORD length = GetModuleFileNameW(nullptr, exePath, MAX_PATH);

    if (length == 0 || length >= MAX_PATH) {
        return false;
    }

    std::wstring directory(exePath, length);
    const std::wstring::size_type pos = directory.find_last_of(L"\\/");

    if (pos == std::wstring::npos) {
        return false;
    }

    directory.resize(pos);
    return SetCurrentDirectoryW(directory.c_str()) != FALSE;
}

int main()
{
    if (!SetWorkingDirectoryToExePath()) {
        return -1;
    }

    // 完成 SDK 初始化后,再调用:
    // zoloz::smile_to_pay::zolozVerify(...);

    return 0;
}

这里没有展开 zolozVerify 的参数,因为不同程序包提供的函数签名可能不同。具体参数应以当前 SDK 附带的头文件和示例代码为准。

对比工程平台和运行库

检查业务工程与 testmain.exe 使用的体系结构是否一致:

配置属性
  → 常规
  → 平台工具集:Visual Studio 2017 (v141)

配置管理器
  → 活动解决方案平台:Win32 或 x64

不能因为操作系统是 64 位,就直接把工程设置为 x64。如果 SDK 只提供 32 位 DLL,业务程序也必须编译为 Win32,反之亦然。

还要检查运行库设置:

配置属性
  → C/C++
  → 代码生成
  → 运行库

建议先使用 Release 配置验证,并按照 SDK 示例工程的设置选择 /MD 或 /MDd。不同位数或不同编译配置的 DLL 不要混用。

可以通过 Visual Studio 的模块窗口、dumpbin /headers 或依赖检查工具确认 EXE 和 DLL 的架构:

dumpbin /headers your_app.exe | findstr machine
dumpbin /headers zoloz_sdk.dll | findstr machine

其中 zoloz_sdk.dll 只是示意名称,需要替换为程序包中的实际 DLL。

检查资源和依赖文件

将业务程序的运行目录与 zoloz_smile2pay_release_200724\bin 对比,重点检查:

  • SDK 主 DLL 是否齐全。
  • 第三方图像处理、渲染和摄像头相关 DLL 是否齐全。
  • 配置、模型、证书或资源目录是否保留了原有层级。
  • DLL 是否被 Windows 安全策略拦截。
  • PATH 中是否存在同名旧版 DLL,导致程序加载了错误版本。

如果直接复制整个 bin 目录后问题消失,通常说明原因在于部署缺失或路径错误。确认原因后,再逐项整理正式发布需要的文件。开始排查时不建议只挑选看起来“有用”的 DLL。

可以使用 Process Monitor 过滤业务程序,观察调用 zolozVerify 时是否大量出现以下记录:

NAME NOT FOUND
PATH NOT FOUND
BAD IMAGE

同时对比 testmain.exe 和业务程序实际加载的 DLL 路径。即使 DLL 名称相同,从不同目录加载也可能产生不同结果。

检查调用线程和消息循环

如果 SDK 示例是在主线程或 GUI 线程中调用 zolozVerify,业务程序也应先采用相同的调用方式。除非当前 SDK 文档明确说明支持,否则不要在普通工作线程中直接创建刷脸窗口。

例如,业务处理可以放在工作线程中,但 SDK 界面调用应投递回窗口线程:

constexpr UINT WM_START_ZOLOZ_VERIFY = WM_APP + 1;

LRESULT MainWindow::WndProc(
    HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
{
    switch (message) {
    case WM_START_ZOLOZ_VERIFY:
        // 使用当前 SDK 头文件定义的真实参数调用。
        // zoloz::smile_to_pay::zolozVerify(...);
        return 0;

    default:
        return DefWindowProcW(hwnd, message, wParam, lParam);
    }
}

// 在其他线程中请求启动时:
PostMessageW(mainWindowHandle, WM_START_ZOLOZ_VERIFY, 0, 0);

如果业务程序是控制台程序,还要确认 SDK 是否依赖 Windows 消息循环。窗口能够出现,不代表消息循环和渲染线程一定正常。

排查渲染环境

确认依赖、路径和工程配置一致后,再检查图形渲染环境:

  • 在本机物理桌面运行,暂时不要通过远程桌面测试。
  • 更新或回退显卡驱动后重新测试。
  • 确认刷脸界面不是由 Windows 服务或 Session 0 启动的。
  • 确认程序没有启用与示例不同的兼容模式。
  • 在双显卡设备上,分别指定集成显卡和独立显卡测试。
  • 如果 SDK 提供软件渲染或关闭硬件加速的正式配置项,可以按照对应版本的文档进行验证,不要自行猜测配置参数。

“窗口白屏”有时只是预览控件没有完成绘制,并不代表摄像头没有采集到图像。需要结合 SDK 日志,分别判断采集初始化和渲染初始化是否成功。

推荐排查顺序

  1. 将业务 EXE 放入官方 bin 目录直接运行。
  2. 把工作目录设置为 $(TargetDir)。
  3. 确认 Win32/x64 与 SDK 完全一致。
  4. 使用与示例工程一致的 Release、运行库和工具集配置。
  5. 对比业务程序与 testmain.exe 加载的 DLL 和资源路径。
  6. 在主线程或 GUI 线程中调用 zolozVerify。
  7. 检查 SDK 日志以及 Process Monitor 中的文件加载失败记录。
  8. 最后排查远程桌面、显卡驱动和硬件加速问题。

如果把业务 EXE 放入官方 bin 目录后仍然白屏,而 testmain.exe 在同一目录中正常运行,问题通常集中在工程位数、运行库、调用线程或初始化顺序。若业务 EXE 放入该目录后恢复正常,则基本可以确定是 DLL、资源部署或工作目录的问题。

备注:内容仅供参考。