A number of people asked me to clarify yesterday's entry. Rather than try to talk you through it, I think the code is straightforward enough to speak for itself. Here's a little skeleton that I just whipped up.
#include <stdio.h>#include <activscp.h>#include <new>
const GUID CLSID_VBScript = {0xb54f3741, 0x5b07, 0x11cf, {0xa4, 0xb0, 0x00, 0xaa, 0x00, 0x4a, 0x55, 0xe8}};const GUID CLSID_JScript = {0xf414c260, 0x6ac0, 0x11cf, {0xb6, 0xd1, 0x00, 0xaa, 0x00, 0xbb, 0xbb, 0x58}};
class MySite : public IActiveScriptSite {private:
ULONG m_cref; virtual ~MySite() {}
public:
MySite() { this->m_cref = 1; }
STDMETHOD_(ULONG, AddRef)() { return ++this->m_cref; }
STDMETHOD_(ULONG,Release)() { --this->m_cref; if (this->m_cref == 0) { delete this; return 0; } return this->m_cref; }
STDMETHOD(QueryInterface)(REFIID iid, void ** ppv) { if (ppv == NULL) return E_POINTER; if (IsEqualIID(iid, IID_IUnknown)) *ppv = (IUnknown*)this; else if (IsEqualIID(iid, IID_IActiveScriptSite)) *ppv = (IActiveScriptSite*)this; else { *ppv = NULL; return E_NOINTERFACE; } this->AddRef(); return S_OK; }
STDMETHOD(GetLCID)(LCID * plcid) { return E_NOTIMPL; }
STDMETHOD(GetItemInfo)( LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown ** ppunkItem, ITypeInfo ** ppti) { return E_NOTIMPL; }
STDMETHOD(GetDocVersionString)(BSTR * pbstrVersion) { return E_NOTIMPL; }
STDMETHOD(OnScriptTerminate)( const VARIANT * pvarResult, const EXCEPINFO * pexcepinfo) { return S_OK; }
STDMETHOD(OnStateChange)(SCRIPTSTATE state) { return S_OK; }
STDMETHOD(OnEnterScript)() { return S_OK; } STDMETHOD(OnLeaveScript)() { return S_OK; }
STDMETHOD(OnScriptError)(IActiveScriptError * perror) { EXCEPINFO excepinfo; LONG column = 0; ULONG line = 0; DWORD context = 0; BSTR bstrLine = NULL; memset(&excepinfo, 0x00, sizeof excepinfo); perror->GetExceptionInfo(&excepinfo); if (excepinfo.pfnDeferredFillIn != NULL) excepinfo.pfnDeferredFillIn(&excepinfo); perror->GetSourceLineText(&bstrLine); perror->GetSourcePosition(&context, &line, &column);
wprintf(L"Error on line %ld column %ld\n", line, column); if (bstrLine != NULL) wprintf(L"Line: %s\n", bstrLine); if (excepinfo.bstrDescription != NULL) wprintf(L"Description: %s\n", excepinfo.bstrDescription); if (excepinfo.bstrSource != NULL) wprintf(L"Source: %s\n", excepinfo.bstrSource); if (excepinfo.bstrHelpFile != NULL) wprintf(L"Help: %s\n", excepinfo.bstrHelpFile);
SysFreeString(bstrLine); SysFreeString(excepinfo.bstrDescription); SysFreeString(excepinfo.bstrSource); SysFreeString(excepinfo.bstrHelpFile);
return S_OK; }};
void main() { HRESULT hr = S_OK; HRESULT hrInit; IClassFactory * pfactory = NULL; IActiveScript * pscript = NULL; IActiveScriptParse * pparse = NULL; IActiveScriptSite * psite = NULL;
hr = hrInit = OleInitialize(NULL); if (FAILED(hr)) goto LError;
hr = CoGetClassObject(CLSID_VBScript, CLSCTX_SERVER, NULL, IID_IClassFactory, (void**)&pfactory); if (FAILED(hr)) goto LError;
hr = pfactory->CreateInstance(NULL, IID_IActiveScript, (void**)&pscript); if (FAILED(hr)) goto LError;
psite = new(std::nothrow) MySite(); if (psite == NULL) { hr = E_OUTOFMEMORY; goto LError; }
hr = pscript->SetScriptSite(psite); if (FAILED(hr)) goto LError;
hr = pscript->QueryInterface(IID_IActiveScriptParse, (void**)&pparse); if (FAILED(hr)) goto LError;
hr = pparse->ParseScriptText(L"Function Foo \n Foo = 123 \n End Funtcion \n", NULL, NULL, NULL, 0, 1, 0, NULL, NULL);
if (FAILED(hr)) goto LError; LError:
if (FAILED(hr)) printf("%0x\n", hr);
if (pparse != NULL) pparse->Release();
if (psite != NULL) psite->Release();
if (pscript != NULL) { pscript->Close(); pscript->Release(); }
if (pfactory != NULL) pfactory->Release();
if (SUCCEEDED(hrInit)) OleUninitialize();}
As you would expect, this program prints out the information about the error, and ParseScriptText returns SCRIPT_E_REPORTED to indicate that there was an error but it has already been reported. Had there been no error, the script would not have actually run; the engine is not started, just initialized.
Error on line 3 column 5Line: End FuntcionDescription: Expected 'Function'Source: Microsoft VBScript compilation error80020101