关于在Windows服务中实现IQueryCancelAutoPlay的问题

时间:2010-04-07 09:58:03

标签: visual-c++ com windows-services

我正在实现IQueryCancelAutoPlay COM接口并使用Windows服务*中的运行对象表进行注册。

我的问题是,当我插入大容量存储设备(或任何设备)时,它永远不会被称为。以下是一些更多信息:

我在ROT注册的代码:

Text::string clsIdString = Text::to_string(Com::CLSID_QCAListener);
// remove curly braces
clsIdString = clsIdString.substr(1, clsIdString.length() - 2);

// set registry key to make sure we get notifications from windows
Reg::SetValue(HKEY_LOCAL_MACHINE, 
_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoplayHandlers\\CancelAutoplay\\CLSID"),
clsIdString, _T(""));

HRESULT result = S_OK;

// create class moniker ...
CComPtr<IMoniker> moniker;
result = CreateClassMoniker(Com::CLSID_QCAListener, &moniker);
if( !ValidateResult(result, "Error creating class moniker") )
return;

DBG << _T("Getting IRunningObjectTable pointer ...") << std::endl;

// get running oject table ... 
CComPtr<IRunningObjectTable> runningObjectTable;
result = GetRunningObjectTable(0, &runningObjectTable);
if( !ValidateResult(result, "Error getting running object table") )
return;

// create an instance of the QCAListener class ...
Com::QCAListener * listenerInstance = new Com::QCAListener();
if(!ValidateResult( listenerInstance != 0,
"Error creating QueryCancelAutoplayListener"))
return;
// ... and set the pointer in the _qcaListener variable
CComPtr<IQueryCancelAutoPlay> qcaListener;
listenerInstance->QueryInterface(IID_IQueryCancelAutoPlay, reinterpret_cast<void**>(&qcaListener));

DBG << _T("Registering IQueryCancelAutoPlay with ROT ...") << std::endl;
result = runningObjectTable->Register(
ROTFLAGS_REGISTRATIONKEEPSALIVE,
listenerInstance,
moniker,
&_qcaRegistration);
ValidateResult(result, "Error registering QueryCancelAutoplayListener with the ROT");

runningObjectTable-&gt;寄存器返回S_OK,并且在代码块执行结束时,listenerInstance的ref-count为1(如果我删除对runningObjectTable的调用 - >完全注册,则qcaListener时ref-count保持为0超出范围所以这意味着我的类的实例在ROT中保持活动状态。

更多详细信息:在开发过程中,我的服务使用我的帐户凭据(本地管理员)运行。虽然这可能会改变,但它应该与当前配置一样工作。

任何人都可以对此有所了解吗?


* - 我知道文档说我不应该在服务中实现IQueryCancelAutoPlay,但我需要这样做是出于各种原因(业务需求等)。

1 个答案:

答案 0 :(得分:1)

我明白了(对于那些在遇到类似问题时偶然发现这个答案的人):

该服务在不同的窗口站和不同的桌面下运行。在IQueryCalcelAutoPlay中注册了ROT实施时,这是针对不同的桌面进行的。

当插入新的USB设备时,当前用户的桌面shell(资源管理器)将无法找到此注册(因为它未在当前桌面中注册)。