IDebugProgramProvider2::WatchForProviderEvents
프로세스가 포트 이벤트에 대한 알림을 받을 수 있도록 합니다.
구문
int WatchForProviderEvents(
enum_PROVIDER_FLAGS Flags,
IDebugDefaultPort2 pPort,
AD_PROCESS_ID ProcessId,
CONST_GUID_ARRAY EngineFilter,
ref Guid guidLaunchingEngine,
IDebugPortNotify2 pEventCallback
);
매개 변수
Flags
[in] PROVIDER_FLAGS 열거형의 플래그 조합입니다. 이 호출에는 다음과 같은 플래그가 일반적입니다.
Flag | 설명 |
---|---|
PFLAG_REMOTE_PORT |
호출자가 원격 머신에서 실행되고 있습니다. |
PFLAG_DEBUGGEE |
현재 호출자가 디버그되고 있습니다(마샬링에 대한 추가 정보가 각 노드에 대해 반환됨). |
PFLAG_ATTACHED_TO_DEBUGGEE |
호출자가 연결되었지만 디버거에 의해 시작되지 않았습니다. |
PFLAG_REASON_WATCH |
호출자가 이벤트를 감시하려고 합니다. 이 플래그가 설정되지 않은 경우 콜백 이벤트가 제거되고 호출자가 더 이상 알림을 받지 않습니다. |
pPort
[in] 호출 프로세스가 실행 중인 포트입니다.
processId
[in] 해당 프로그램을 포함하는 프로세스의 ID를 보유 중인 AD_PROCESS_ID 구조체입니다.
EngineFilter
[in] 프로세스와 연결된 디버그 엔진의 GUID 배열입니다.
guidLaunchingEngine
[in] 이 프로세스를 시작한 디버그 엔진의 GUID입니다(있는 경우).
pEventCallback
[in] 이벤트 알림을 받는 IDebugPortNotify2 개체입니다.
Return Value
성공하면 S_OK
를 반환하고, 실패하면 오류 코드를 반환합니다.
설명
호출자가 이 메서드에 대한 이전 호출로 설정된 이벤트 처리기를 제거하려는 경우 호출자는 처음과 동일한 매개 변수를 전달하지만 PFLAG_REASON_WATCH
플래그를 해제합니다.
예시
다음 예제에서는 IDebugProgramProvider2 인터페이스를 노출하는 CDebugEngine 개체에 대해 이 메서드를 구현하는 방법을 보여 줍니다.
STDMETHODIMP CDebugEngine::WatchForProviderEvents(
PROVIDER_FLAGS Flags,
IDebugDefaultPort2 *pPort,
AD_PROCESS_ID processId,
CONST_GUID_ARRAY EngineFilter,
REFGUID guidLaunchingEngine,
IDebugPortNotify2 *pPortNotify)
{
HRESULT hRes = E_FAIL;
if (EVAL(pPort != NULL) && EVAL(pPortNotify != NULL))
{
// We will only watch/send events about the process if the debugger
// is actually debugging the process, and only if this is an attach or a LoRIE launch
if (IsFlagSet(Flags, PFLAG_DEBUGGEE) &&
guidLaunchingEngine == GUID_NULL &&
processId.ProcessIdType == AD_PROCESS_ID_SYSTEM)
{
// We don't support WatchForProviderEvents when in interop mode
if (m_fInterop)
{
ASSERT(!"Shouldn't ever be called in interop mode");
hRes = E_FAIL;
}
else
{
if (IsFlagSet(Flags, PFLAG_REASON_WATCH))
{
// QI to get IDebugEventCallback2 which is required.
CComQIPtr<IDebugEventCallback2> pCallback(pPortNotify);
ASSERT(pCallback != NULL);
if ( pCallback != NULL )
{
// Register the callback
hRes = this->InitDebugSession(pCallback);
if ( S_OK == hRes )
{
// Get the IDebugProcess2 from the port and call AttachImpl
CComPtr<IDebugProcess2> spProcess;
hRes = pPort->GetProcess(processId, &spProcess);
if (HREVAL(S_OK, hRes))
{
hRes = AttachImpl(spProcess, NULL, NULL, processId.ProcessId.dwProcessId, ATTACH_REASON_USER, NULL);
if ( FAILED(hRes) && (!m_pPidList || 0 == m_pPidList->GetCount()) )
this->Cleanup();
}
}
else
this->Cleanup();
}
else
hRes = E_FAIL;
}
else
{
// Detach will be done by SDM calling on programs directly if there are managed programs.
// This handling is the case where no managed code ever ran.
if ( this->IsProcessBeingDebugged(processId.ProcessId.dwProcessId) )
{
ProgramList *pProgList = this->GetProgramListCopy();
if ( EVAL(pProgList) )
{
if ( pProgList->GetCount() == 0)
{
CComPtr<ICorDebugProcess> pCorProcess;
hRes = this->GetCorProcess(processId.ProcessId.dwProcessId, &pCorProcess);
if (HREVAL(S_OK, hRes) )
{
hRes = pCorProcess->Stop(INFINITE);
if ( HREVAL(S_OK, hRes) )
hRes = pCorProcess->Detach();
}
// Tell the engine that it should unregister this process from com+
this->UnregisterProcess(processId.ProcessId.dwProcessId);
// If there are no more pids left then cleanup everything.
if ( 0 == m_pPidList->GetCount() )
this->Cleanup();
}
// This is needed for cases where the SDM has not yet received program create
// by the time that we need to detach (example: the managed attach succeeds,
// but some other attach step fails).
else
{
PROGNODE *pProgNode = NULL;
while ( pProgNode = pProgList->Next(pProgNode) )
{
CDebugProgram * pProgram = ((CDebugProgram *)pProgNode->data);
hRes = pProgram->Detach();
}
}
delete pProgList;
}
}
else
hRes = S_OK;
}
}
}
else
{
hRes = S_FALSE;
}
}
else
{
hRes = E_INVALIDARG;
}
return hRes;
}