Skill 126 · Zoom Meeting SDK Windows
Subchapter 126.23
troubleshooting/windows-message-loop.mdMarkdown10 KBView on GitHub
Symptom: Authentication times out, callbacks never execute
[AUTH] Calling SDKAuth...
[AUTH] Waiting for callback...
[Still waiting after 30 seconds...]
ERROR: Authentication timeoutRoot Cause: The Zoom Windows SDK uses the Windows message pump to dispatch callbacks. Without processing Windows messages, callbacks are queued but never delivered.
The SDK uses COM/Windows messaging for asynchronous operations:
GetMessage() or PeekMessage()Without message processing: Messages queue up → Never dispatched → Callbacks never fire → Timeout
Use when you need to check conditions or implement timeouts:
bool WaitForAuthentication() {
auto startTime = std::chrono::steady_clock::now();
while (!g_authenticated && !g_exit) {
// CRITICAL: Process Windows messages for SDK callbacks!
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Check timeout
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::steady_clock::now() - startTime).count();
if (elapsed >= 30) {
return false; // Timeout
}
// Small sleep to avoid CPU spinning
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return g_authenticated;
}Use for main application loop:
int main() {
// ... initialize SDK, authenticate, join meeting ...
// Main message loop
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
if (msg.message == WM_QUIT) {
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Cleanup
CleanUPSDK();
return 0;
}Combines non-blocking message processing with custom exit conditions:
// During authentication wait
while (!g_authenticated && !g_exit) {
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
// Main application loop
while (!g_exit) {
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
g_exit = true;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Do other work here
ProcessVideoFrames();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}// This will NEVER work - callbacks never dispatched!
while (!g_authenticated) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}// Callbacks won't fire - no message processing!
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock, []{ return g_authenticated; });while (!g_authenticated) {
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}You MUST process Windows messages in these scenarios:
authService->SDKAuth(authContext);
// MUST process messages while waiting
while (!authenticated) {
ProcessMessages();
}meetingService->Join(joinParam);
// MUST process messages while waiting
while (meetingStatus != IN_MEETING) {
ProcessMessages();
}// MUST continuously process messages
while (!exit) {
ProcessMessages();
}Any time you’re waiting for:
onAuthenticationReturn()onMeetingStatusChanged()onRawDataFrameReceived()You MUST be processing Windows messages!
Symptoms:
Quick Test: Add logging in your callback:
void onAuthenticationReturn(AuthResult ret) {
std::cout << "CALLBACK FIRED!" << std::endl; // Does this ever print?
}If you never see “CALLBACK FIRED!”, you’re not processing messages.
void ProcessMessagesWithDebug() {
MSG msg;
int messageCount = 0;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
messageCount++;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (messageCount > 0) {
std::cout << "Processed " << messageCount << " messages" << std::endl;
}
}| Feature | PeekMessage | GetMessage |
|---|---|---|
| Blocking | No | Yes |
| Returns if no messages | Immediately | Waits |
| Good for | Timeouts, conditions | Main message loop |
| CPU Usage | Can spin (add sleep) | Efficient |
| Flexibility | High | Low |
PeekMessage:
GetMessage:
#include <windows.h>
#include <zoom_sdk.h>
#include <auth_service_interface.h>
#include <iostream>
#include <chrono>
#include <thread>
using namespace ZOOM_SDK_NAMESPACE;
bool g_authenticated = false;
bool g_exit = false;
class MyAuthListener : public IAuthServiceEvent {
public:
void onAuthenticationReturn(AuthResult ret) override {
std::cout << "Auth callback received!" << std::endl;
if (ret == AUTHRET_SUCCESS) {
g_authenticated = true;
}
}
// ... other required methods ...
};
bool AuthenticateWithMessageLoop(IAuthService* authService, const wchar_t* jwt) {
authService->SetEvent(new MyAuthListener());
AuthContext context;
context.jwt_token = jwt;
if (authService->SDKAuth(context) != SDKERR_SUCCESS) {
return false;
}
// Wait for callback with message processing
auto startTime = std::chrono::steady_clock::now();
while (!g_authenticated && !g_exit) {
// Process Windows messages - CRITICAL!
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Check timeout (30 seconds)
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::steady_clock::now() - startTime).count();
if (elapsed >= 30) {
std::cerr << "Authentication timeout" << std::endl;
return false;
}
// Small sleep to avoid CPU spinning
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return g_authenticated;
}
int main() {
// Initialize SDK
InitParam initParam;
initParam.strWebDomain = L"https://zoom.us";
InitSDK(initParam);
// Create auth service
IAuthService* authService = nullptr;
CreateAuthService(&authService);
// Authenticate with message loop
if (!AuthenticateWithMessageLoop(authService, L"your-jwt-token")) {
std::cerr << "Authentication failed" << std::endl;
return 1;
}
std::cout << "Authenticated successfully!" << std::endl;
// Main application loop with message processing
while (!g_exit) {
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
g_exit = true;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Do other work
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
// Cleanup
CleanUPSDK();
return 0;
}