VDS(虚拟磁盘服务)COM 接口通知 - 回调(接收器)仅在注销期间调用(不建议)
Posted
技术标签:
【中文标题】VDS(虚拟磁盘服务)COM 接口通知 - 回调(接收器)仅在注销期间调用(不建议)【英文标题】:VDS (Virtual Disk Service) COM interface notifications - callback (sink) invoked only during unregister (Unadvise) 【发布时间】:2013-11-25 17:23:59 【问题描述】:我想使用 VDS COM 接口在 Windows 中获取有关磁盘添加/删除 (PnP) 的通知(需要支持 Windows 7,因此我无法使用新的“Windows 存储管理 API”)。
这是我的回调类:
class SimpleNotifySink: public IVdsAdviseSink
public:
SimpleNotifySink() : ref(1)
HRESULT OnNotify(
LONG lNumberOfNotifications,
VDS_NOTIFICATION *pNotificationArray
)
printf("Got %d notifications:\n", lNumberOfNotifications);
return S_OK;
ULONG AddRef()
InterlockedIncrement(&ref);
return ref;
ULONG Release()
ULONG ulRefCount = InterlockedDecrement(&ref);
if (0 == ref)
delete this;
return ulRefCount;
HRESULT QueryInterface(REFIID riid, void **ppvObj)
// Always set out parameter to NULL, validating it first.
if (!ppvObj)
return E_INVALIDARG;
*ppvObj = NULL;
if ((riid == IID_IUnknown) || (riid == IID_IVdsAdviseSink))
// Increment the reference count and return the pointer.
*ppvObj = (LPVOID)this;
AddRef();
return S_OK;
return E_NOINTERFACE;
private:
LONG ref;
;
这里是回调注册(sn-p):
IVdsAdviseSink *sink = new SimpleNotifySink();
DWORD cookie = 0;
hr = pService->Advise(sink, &cookie);
if (FAILED(hr))
printf("sink registration (pService->Advise) failed with %X.\n", hr);
printf("press any key...\n");
getchar();
if (cookie != 0)
hr = pService->Unadvise(cookie);
为了测试代码,在“按任意键...”期间,我禁用和启用了一个虚拟磁盘(在 VM 中)——但我的回调仅在 pService->Unadvise 时被调用(我使用了 windbg) (...) 被调用。
有什么想法吗?
谢谢
【问题讨论】:
也许您订阅了错误的线程和/或您没有在此 STA 线程上发送窗口消息,最终无法控制 API 来传递通知。下一次机会只有Unadvise
...
【参考方案1】:
getchar
不发送消息,因此无法发送任何 COM 事件。用消息泵循环替换您的 printf/getchar;像这样:
HRESULT WaitAndPumpMessagesUntilKeyDown(DWORD dwMs)
HRESULT hr = S_OK;
BOOL fContinue = TRUE;
HANDLE hTimer = NULL;
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = -100000LL * dwMs;
// Create an unnamed waitable timer.
hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
if (NULL == hTimer)
return HRESULT_FROM_WIN32(GetLastError());
// Set a timer to wait for 10 seconds.
if (!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0))
return HRESULT_FROM_WIN32(GetLastError());
while (fContinue)
DWORD dwWaitId = ::MsgWaitForMultipleObjectsEx(1, &hTimer, dwMs, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
switch (dwWaitId)
case WAIT_OBJECT_0:
fContinue = FALSE;
break;
case WAIT_OBJECT_0 + 1:
MSG Msg;
while (::PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
::TranslateMessage(&Msg);
if (Msg.message == WM_KEYDOWN)
fContinue = FALSE;
hr = S_OK;
else
::DispatchMessage(&Msg);
break;
case WAIT_TIMEOUT:
hr = S_FALSE;
fContinue = FALSE;
break;
default:// Unexpected error
fContinue = FALSE;
hr = E_FAIL;
break;
return hr;
【讨论】:
以上是关于VDS(虚拟磁盘服务)COM 接口通知 - 回调(接收器)仅在注销期间调用(不建议)的主要内容,如果未能解决你的问题,请参考以下文章