Udostępnij za pośrednictwem


IDebugProgramProvider2::WatchForProviderEvents

Umożliwia powiadamianie procesu o zdarzeniach portów.

Składnia

int WatchForProviderEvents(
   enum_PROVIDER_FLAGS   Flags,
   IDebugDefaultPort2    pPort,
   AD_PROCESS_ID         ProcessId,
   CONST_GUID_ARRAY      EngineFilter,
   ref Guid              guidLaunchingEngine,
   IDebugPortNotify2     pEventCallback
);

Parametry

Flags
[in] Kombinacja flag z wyliczenia PROVIDER_FLAGS . Następujące flagi są typowe dla tego wywołania:

Flaga opis
PFLAG_REMOTE_PORT Obiekt wywołujący jest uruchomiony na maszynie zdalnej.
PFLAG_DEBUGGEE Obiekt wywołujący jest obecnie debugowany (dodatkowe informacje o marshallingu są zwracane dla każdego węzła).
PFLAG_ATTACHED_TO_DEBUGGEE Obiekt wywołujący został dołączony do debugera, ale nie został uruchomiony.
PFLAG_REASON_WATCH Obiekt wywołujący chce oglądać zdarzenia. Jeśli ta flaga nie jest ustawiona. następnie zdarzenie wywołania zwrotnego zostanie usunięte, a obiekt wywołujący nie otrzyma już powiadomień.

pPort
[in] Port, na którym działa proces wywołujący.

processId
[in] Struktura AD_PROCESS_ID zawierająca identyfikator procesu, który zawiera kwestionowany program.

EngineFilter
[in] Tablica identyfikatorów GUID aparatów debugowania skojarzonych z procesem.

guidLaunchingEngine
[in] Identyfikator GUID aparatu debugowania, który uruchomił ten proces (jeśli istnieje).

pEventCallback
[in] Obiekt IDebugPortNotify2 , który odbiera powiadomienia o zdarzeniach.

Wartość zwracana

Jeśli operacja powiedzie się, zwraca wartość S_OK; w przeciwnym razie zwraca kod błędu.

Uwagi

Gdy obiekt wywołujący chce usunąć program obsługi zdarzeń, który został ustanowiony przy użyciu poprzedniego wywołania do tej metody, obiekt wywołujący przekazuje te same parametry, co po raz pierwszy, ale opuszcza flagę PFLAG_REASON_WATCH .

Przykład

W poniższym przykładzie pokazano, jak zaimplementować tę metodę dla obiektu CDebugEngine , który uwidacznia interfejs IDebugProgramProvider2 .

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;
}

Zobacz też