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 接口通知 - 回调(接收器)仅在注销期间调用(不建议)的主要内容,如果未能解决你的问题,请参考以下文章

如何将正在运行的 Oracle 数据库迁移到另一个系统

vmware无法添加主机vmotion功能

虚拟网络中几个重要的术语

虚拟分布式交换机(VDS)

wemall app商城源码Android之通用通知接口demo

关于VMware vSphere 直接将主机从VC中移除,导致该主机VDS丢失记录