ActiveX Scripting Engines: Интерпретация внешнего скрипта в С++ - Собираем всё вместе

ОГЛАВЛЕНИЕ


Собираем всё вместе

С учетом всего описанного ранее, получим последний фрагмент кода – собственно запуск скрипта. В приведенном ниже фрагменте для экономии места я убрал всяческую проверку возвращаемых значений на предмет ошибки.

// Не забываем инициализировать COM библиотеку (сколько раз я наступал на эти грабли!!!)
CoInitializeEx(NULL, COINIT_MULTITHREADED);
    
// А это наш скрипт.
CString script =
        "k = 10 \r\n"
        "dim x \r\n"
        "dim y \r\n"
        "x = 10 \r\n"
        "y = 20 \r\n"
        "VALUE = GetMax(x, y)\r\n"
        "PrintValue(VALUE)\r\n"
        "Message \"Hello, Script!\" \r\n";
        

// Об этих объектах уже столько сказано:
CCodeObject codeobj;
CScriptHost host;


// Глобальное имя объекта скрипта. Это и есть та строка, которая
// (помните?) передается потом как параметр при вызове 
// CScriptHost::GetItemInfo(LPCOLESTR pstrName, ... )
LPCOLESTR pstrObjectName = L"CodeObject";

// Передадим наш codeobj, вернее, его IDispatch интерфейс.
// обьект host его запомнит, а потом, когда будет нужно, передаст в
// при вызове CScriptHost::GetItemInfo(), как говорилось ранее.
host.AssociateNamedObject( codeobj.GetIDispatch(TRUE),       
                           pstrObjectName );
        

// Создаем (инстанциируем) обьекты ActiveX Scripting Engine для
// VBScript. При желании, можно заменить L"VBScript" на L"JScript" для
// JavaScript. В документации Microsoft указано, что возможно 
// использовать также Perl и Lisp, но я не пробовал.

IActiveScript        *pASEngine = NULL;   
IActiveScriptParse   *pISParser = NULL; 

CLSID EngineClsid;
CLSIDFromProgID(L"VBScript", &EngineClsid);
CoCreateInstance(EngineClsid, NULL, CLSCTX_INPROC_SERVER,
             IID_IActiveScript, (void **)&pASEngine);

pASEngine->QueryInterface(IID_IActiveScriptParse, (void**)&pISParser);

// Передаем наш хост-объект – как уже говорилось, engine будет вызывать
// его методы.
pASEngine->SetScriptSite(&host);


// Здесь важен флаг видимости имен SCRIPTITEM_GLOBALMEMBERS.
// Если этот флаг не указывать, нужно потом вызывать ParseScriptText с 
// обязательным  pstrObjectName в качестве второго параметра:
// pISParser->ParseScriptText( pParseText,
//                             pstrObjectName, 
//                             NULL, NULL, 0, 0, 0, NULL, &ei);

pASEngine->AddNamedItem( pstrObjectName, SCRIPTITEM_ISVISIBLE |                       
                         SCRIPTITEM_ISSOURCE |             
                         SCRIPTITEM_GLOBALMEMBERS);

pISParser->InitNew();

// Ну что ж, передаем скрипт для парсинга.
EXCEPINFO ei = {0};
BSTR pParseText = script.AllocSysString();
pISParser->ParseScriptText(pParseText, NULL, NULL, NULL, 0, 0, 0, NULL,    
                           &ei);
SysFreeString(pParseText);


// Всё, пора. Запускаем скрипт на выполнение!!!
pASEngine->SetScriptState(SCRIPTSTATE_CONNECTED);
    

// Ну вот и всё...
pASEngine->Close();
pISParser->Release();
pASEngine->Release();