叫用動作
IUPnPService::InvokeAction方法允許在 Service 物件上叫用動作。 這個方法有兩個輸入參數:動作的名稱,以及該動作的輸入引數陣列。 方法有兩個參數:
- 參數一 — 輸入/輸出參數:該動作的輸出引數陣列。
- 參數二 — 輸出參數:傳回值。
方法會導致在裝置上叫用動作。 如果動作造成裝置的狀態變數變更,裝置會產生事件通知。
VBScript 範例
下列 VBScript 程式碼範例會在 Service 物件上叫用兩個動作。 第一個動作 GetTrackInfo採用一個輸入引數,一個追蹤編號。 GetTrackInfo巨集指令會以傳回值的形式傳回追蹤長度。 如果方法傳回成功,動作也有一個輸出引數,其中包含追蹤標題。
叫用 GetTrackInfo 巨集指令之後,此範例會叫用 Play 巨集指令,該動作不會採用任何引數。 不過,由於 InvokeAction 的語法需要輸入和輸出引數的陣列,因此此範例必須建立空陣列 emptyArgs,且不含任何元素。 此範例會將此陣列傳遞給 InvokeAction ,以取得輸入和輸出引數,以及動作的名稱。
Dim returnVal
Dim outArgs(1)
Dim args(1)
args(0) = 3
returnVal = service.InvokeAction("GetTrackInfo", args, outArgs)
'return Val now contains the track length
'and outArgs(0) contains the track title
Dim emptyArgs(0)
returnVal = service.InvokeAction("Play", emptyArgs, emptyArgs)
'returnVal indicates if the action was successful
C++ 範例
下列範例會定義 C++ 函式,該函式會叫用不含引數的動作。 由於 InvokeAction 需要傳入的 引數 SAFEARRAY ,因此此範例會建立空 的 SAFEARRAY。 由於此動作不會傳回值或具有輸出引數,因此此範例會忽略傳遞至InvokeAction的最後兩個VARIANT值。
如果動作造成裝置的狀態變數變更,裝置會產生事件通知。
#include <windows.h>
#include <upnp.h>
#include <iostream>
#include <iomanip>
#pragma comment(lib, "oleaut32.lib")
using namespace std;
void InvokePlay(IUPnPService * pService)
{
HRESULT hr;
BSTR bstrActionName;
bstrActionName = SysAllocString(L"Play");
if (bstrActionName)
{
SAFEARRAYBOUND rgsaBound[1];
SAFEARRAY * psa = NULL;
rgsaBound[0].lLbound = 0;
rgsaBound[0].cElements = 0;
psa = SafeArrayCreate(VT_VARIANT, 1, rgsaBound);
if (psa)
{
LONG lStatus;
VARIANT varInArgs;
VariantInit(&varInArgs);
varInArgs.vt = VT_VARIANT | VT_ARRAY;
V_ARRAY(&varInArgs) = psa;
hr = pService->InvokeAction(bstrActionName,
varInArgs,
NULL,
NULL);
if (SUCCEEDED(hr))
{
wcout << L"Action invoked successfully\n";
}
else
{
wcerr << L"Failed to invoke action - HRESULT 0x"
<< setbase(16)
<< hr << L"\n";
}
SafeArrayDestroy(psa);
}
else
{
wcerr << L"Failed to create safe array\n";
}
SysFreeString(bstrActionName);
}
else
{
wcerr << L"Failed to allocate action name string\n";
}
}
下列範例會叫用虛構 的 GetTrackInfo 巨集指令。 它會取得追蹤編號做為引數、傳回追蹤長度做為傳回值,並在輸出引數中傳回追蹤標題。 此程式碼與上述範例類似,不同之處在于,此範例不會建立輸入引數的空白 SAFEARRAY ,而是插入包含追蹤編號的 VARIANT 。 如果 InvokeAction 傳回成功,本範例會檢查傳回值和輸出引數的陣列。
#include <windows.h>
#include <upnp.h>
#include <iostream>
#include <iomanip>
#pragma comment(lib, "oleaut32.lib")
using namespace std;
void InvokeGetTrackInfo(IUPnPService * pService)
{
HRESULT hr;
BSTR bstrActionName;
bstrActionName = SysAllocString(L"GetTrackInfo");
if (bstrActionName)
{
SAFEARRAYBOUND rgsaBound[1];
SAFEARRAY * psa = NULL;
rgsaBound[0].lLbound = 0;
rgsaBound[0].cElements = 1;
psa = SafeArrayCreate(VT_VARIANT, 1, rgsaBound);
if (psa)
{
long rgIndices[1];
VARIANT varTrackNum;
rgIndices[0] = 0;
VariantInit(&varTrackNum);
varTrackNum.vt = VT_I4;
// An arbitrary track is chosen (track 3)
V_I4(&varTrackNum) = 3;
hr = SafeArrayPutElement(psa,
rgIndices,
(void *) &varTrackNum);
VariantClear(&varTrackNum);
if (SUCCEEDED(hr))
{
LONG lStatus;
VARIANT varInArgs;
VARIANT varOutArgs;
VARIANT varReturnVal;
VariantInit(&varInArgs);
VariantInit(&varOutArgs);
VariantInit(&varReturnVal);
varInArgs.vt = VT_VARIANT | VT_ARRAY;
V_ARRAY(&varInArgs) = psa;
hr = pService->InvokeAction(bstrActionName,
varInArgs,
&varOutArgs,
&varReturnVal);
if (SUCCEEDED(hr))
{
SAFEARRAY * psaOutArgs = NULL;
VARIANT varTrackTitle;
psaOutArgs = V_ARRAY(&varOutArgs);
VariantInit(&varTrackTitle);
rgIndices[0] = 0;
hr = SafeArrayGetElement(psaOutArgs,
rgIndices,
(void *)&varTrackTitle);
if (SUCCEEDED(hr))
{
wcout << L"Action invoked successfully\n"
<< L"\tTrack Length == "
<< V_I4(&varReturnVal) << L"\n"
<< L"\tTrack Title == "
<< V_BSTR(&varTrackTitle) << L"\n";
}
else
{
wcerr << L"Failed to get array element -"
<< L" HRESULT 0x"
<< setbase(16)
<< hr << L"\n";
}
VariantClear(&varTrackTitle);
VariantClear(&varReturnVal);
VariantClear(&varOutArgs);
}
else
{
wcerr << L"Failed to invoke action - HRESULT 0x"
<< setbase(16)
<< hr << L"\n";
}
}
else
{
wcerr << L"Failed to insert argument into array - "
<< L"HRESULT 0x"
<< setbase(16)
<< hr << L"\n";
}
SafeArrayDestroy(psa);
}
else
{
wcerr << L"Failed to create safe array\n";
}
SysFreeString(bstrActionName);
}
else
{
wcerr << L"Failed to allocate action name string\n";
}
}