Freigeben über


Registrieren eines Rückrufs

Wenn die Anwendung eine Benachrichtigung erfordert, wenn sich der Wert einer Zustandsvariable ändert oder der von ihr dargestellte Dienst instance nicht verfügbar ist, muss die Anwendung eine Rückruffunktion registrieren. Um eine Rückruffunktion für das aufzurufende Dienstobjekt zu registrieren, verwenden Sie die IUPnPService::AddCallback-Methode . Diese Methode kann verwendet werden, um mehrere Rückrufe zu registrieren.

Entwickler sollten einen asynchronen Vorgang innerhalb eines asynchronen Rückrufs nicht abbrechen.

Hinweis

Das Hinzufügen eines Rückrufs in Visual Basic unterscheidet sich von der in VBScript verwendeten Methode. Die in VBScript verwendete GetRef-Funktion ist in Visual Basic nicht verfügbar. Daher muss ein Entwickler ein IDispatch-Objekt erstellen, das über die Rückruffunktion als Standardmethode verfügt. Weitere Informationen finden Sie unter Registrieren eines Rückrufs in Visual Basic.

 

VBScript-Beispiel

Der folgende VBScript-Code definiert die Rückruffunktion serviceChangeCallback, die aufgerufen werden soll, wenn sich die Werte von Zustandsvariablen ändern oder wenn der Dienst instance nicht mehr verfügbar ist. Die Funktion verfügt über vier Argumente.

Das erste Argument für die Funktion gibt den Grund an, aus dem der Rückruf aufgerufen wird. Sie wird entweder aufgerufen, weil sich eine Zustandsvariable geändert hat oder weil der Dienst instance nicht mehr verfügbar ist.

Das zweite Argument ist das Service-Objekt, für das der Rückruf aufgerufen wird. Wenn der Rückruf für eine Zustandsvariablenänderung aufgerufen wird, werden der Funktion zwei zusätzliche Argumente übergeben: der Name der Variablen, die sich geändert hat, und ihr neuer Wert.

In diesem Beispiel zeigt der Rückruf einfach ein Meldungsfeld an, das den Namen der geänderten Variablen und den neuen Wert anzeigt, und ob der Rückruf für eine Zustandsvariablenänderung aufgerufen wurde. Andernfalls wird eine Meldung angezeigt, die angibt, dass der Dienst instance nicht mehr verfügbar ist.

Der letzte Teil des Codefragments zeigt, wie die Rückruffunktion mithilfe der AddCallback-Methode registriert wird. Es wird davon ausgegangen, dass die Dienstobjektvariablen appService und xportService initialisiert wurden, wie unter Abrufen von Dienstobjekten gezeigt.

'State Change Callback Function
 
'Note:  In the sub declaration statement below, VARIABLE_UPDATE
'is one of two possible values for the callbackType argument; 
'the other is SERVICE_INSTANCE_DIED

Sub serviceChangeCallback(callbacktype, svcObj, varName, value)
    If (callbacktype = "VARIABLE_UPDATE") then
        Dim outString
        outString = "State Variable Changed:" & vbCrLf
        outString = outString & varName & " == " & value
    
        MsgBox(outString, "Service Callback")
    Else if (callbacktype = "SERVICE_INSTANCE_DIED") then
        MsgBox("Service instance is no longer available", 
               "Service Callback")
    End If
End Sub

' ...
    
'Add our state change callback to each service
appService.AddCallback GetRef("serviceChangeCallback")
xportService.AddCallback GetRef("serviceChangeCallback")

C++-Beispiel

#include <windows.h>
#include <upnp.h>
#include <stdio.h>

#pragma comment(lib, "oleaut32.lib")

class CUPnPServiceCallback : public IUPnPServiceCallback
{
public:
    CUPnPServiceCallback()
    {
        m_lRefCount = 0;
    };
    
    STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject)
    {
        HRESULT hr = S_OK;
        
        if(NULL == ppvObject)
        {
            hr = E_POINTER;
        }
        else
        {
            *ppvObject = NULL;
        }
        
        if(SUCCEEDED(hr))
        {
            if(IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IUPnPServiceCallback))
            {
                *ppvObject = static_cast<IUPnPServiceCallback*>(this);
                AddRef();
            }
            else
            {
                hr = E_NOINTERFACE;
            }
        }
        
        return hr;
    };
    
    STDMETHODIMP_(ULONG) AddRef()
    {
        return ::InterlockedIncrement(&m_lRefCount);
    };
    
    STDMETHODIMP_(ULONG) Release()
    {
        LONG lRefCount = ::InterlockedDecrement(&m_lRefCount);
        if(0 == lRefCount)
        {
            delete this;
        }
        
        return lRefCount;
    };
    
    STDMETHODIMP StateVariableChanged(IUPnPService *pus, LPCWSTR pcwszStateVarName, VARIANT varValue)
    {
        HRESULT    hr = S_OK;
        BSTR ServiceId;
        hr = pus->get_Id(&ServiceId);
        if (SUCCEEDED(hr))
        {
            VARIANT AlphaVariant;
            VariantInit(&AlphaVariant);
            hr = VariantChangeType(&AlphaVariant, &varValue, VARIANT_ALPHABOOL, VT_BSTR);
            if(SUCCEEDED(hr))
            {
                printf("StateVariableChanged called for the %S service"
                       " for %S state variable with the value=%S.\n",
                        ServiceId, pcwszStateVarName, V_BSTR(&AlphaVariant));
                VariantClear(&AlphaVariant);
            }
            SysFreeString(ServiceId);
        }
        return hr;
    };

    STDMETHODIMP ServiceInstanceDied(IUPnPService *pus)
    {
        HRESULT hr = S_OK;
        BSTR ServiceType;
        hr = pus->get_ServiceTypeIdentifier(&ServiceType);
        if(SUCCEEDED(hr))
        {
            printf("ServiceInstanceDied called for the %S service!\n", ServiceType);
            SysFreeString(ServiceType);
        }
        return hr;
    };
    
private:
    LONG m_lRefCount;
    
};

HRESULT AddCallbackToService(IUPnPService* pUPnPService)
{
    HRESULT hr = S_OK;

    IUnknown* pUPnPServiceCallback = new CUPnPServiceCallback;
    if(NULL != pUPnPServiceCallback)
    {
        pUPnPServiceCallback->AddRef();
        hr = pUPnPService->AddCallback(pUPnPServiceCallback);
        pUPnPServiceCallback->Release();
    }
    else
    {
        hr = E_OUTOFMEMORY;
    }
    return hr;
}