How to load & call a VBScript function from within C++?

后端 未结 2 1666
时光取名叫无心
时光取名叫无心 2020-12-03 12:34

We have customers asking for VBScript functions to be called when particular actions occur within our product. I\'ve been trying to research the Windows Scripting technologi

2条回答
  •  Happy的楠姐
    2020-12-03 13:17

    I've put together a "Hello World" IActiveScript C++ ATL console application that:

    • Define CSimpleScriptSite class
      • Implement IActiveScriptSite interface (mandatory)
      • Implement IActiveScriptSiteWindow interface (optional)
      • Minimum implementation with most functions implemented with a dummy stub
      • Has no error handling. Consult MSDN IActiveScriptError.
    • Use CoCreateInstance a new IActiveSite object
      • Create instances of both VBScript and JScript
      • Link the IActiveSite to IActiveScriptSite using IActiveSite::SetScriptSite
      • Call QueryInterface to get an IActiveScriptParse interface
      • Use IActiveScriptParse to execute VBScript or JScript code
    • The sample:
      • Evaluates an expression in JScript
      • Evaluates an expression in VBScript
      • Runs a command in VBScript

    Code:

    #include "stdafx.h"
    #include 
    #include 
    
    class CSimpleScriptSite :
        public IActiveScriptSite,
        public IActiveScriptSiteWindow
    {
    public:
        CSimpleScriptSite() : m_cRefCount(1), m_hWnd(NULL) { }
    
        // IUnknown
    
        STDMETHOD_(ULONG, AddRef)();
        STDMETHOD_(ULONG, Release)();
        STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject);
    
        // IActiveScriptSite
    
        STDMETHOD(GetLCID)(LCID *plcid){ *plcid = 0; return S_OK; }
        STDMETHOD(GetItemInfo)(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) { return TYPE_E_ELEMENTNOTFOUND; }
        STDMETHOD(GetDocVersionString)(BSTR *pbstrVersion) { *pbstrVersion = SysAllocString(L"1.0"); return S_OK; }
        STDMETHOD(OnScriptTerminate)(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) { return S_OK; }
        STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState) { return S_OK; }
        STDMETHOD(OnScriptError)(IActiveScriptError *pIActiveScriptError) { return S_OK; }
        STDMETHOD(OnEnterScript)(void) { return S_OK; }
        STDMETHOD(OnLeaveScript)(void) { return S_OK; }
    
        // IActiveScriptSiteWindow
    
        STDMETHOD(GetWindow)(HWND *phWnd) { *phWnd = m_hWnd; return S_OK; }
        STDMETHOD(EnableModeless)(BOOL fEnable) { return S_OK; }
    
        // Miscellaneous
    
        HRESULT SetWindow(HWND hWnd) { m_hWnd = hWnd; return S_OK; }
    
    public:
        LONG m_cRefCount;
        HWND m_hWnd;
    };
    
    STDMETHODIMP_(ULONG) CSimpleScriptSite::AddRef()
    {
        return InterlockedIncrement(&m_cRefCount);
    }
    
    STDMETHODIMP_(ULONG) CSimpleScriptSite::Release()
    {
        if (!InterlockedDecrement(&m_cRefCount))
        {
            delete this;
            return 0;
        }
        return m_cRefCount;
    }
    
    STDMETHODIMP CSimpleScriptSite::QueryInterface(REFIID riid, void **ppvObject)
    {
        if (riid == IID_IUnknown || riid == IID_IActiveScriptSiteWindow)
        {
            *ppvObject = (IActiveScriptSiteWindow *) this;
            AddRef();
            return NOERROR;
        }
        if (riid == IID_IActiveScriptSite)
        {
            *ppvObject = (IActiveScriptSite *) this;
            AddRef();
            return NOERROR;
        }
        return E_NOINTERFACE;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        HRESULT hr = S_OK;
        hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    
        // Initialize
        CSimpleScriptSite* pScriptSite = new CSimpleScriptSite();
        CComPtr spJScript;
        CComPtr spJScriptParse;
        hr = spJScript.CoCreateInstance(OLESTR("JScript"));
        hr = spJScript->SetScriptSite(pScriptSite);
        hr = spJScript->QueryInterface(&spJScriptParse);
        hr = spJScriptParse->InitNew();
        CComPtr spVBScript;
        CComPtr spVBScriptParse;
        hr = spVBScript.CoCreateInstance(OLESTR("VBScript"));
        hr = spVBScript->SetScriptSite(pScriptSite);
        hr = spVBScript->QueryInterface(&spVBScriptParse);
        hr = spVBScriptParse->InitNew();
    
        // Run some scripts
        CComVariant result;
        EXCEPINFO ei = { };
        hr = spJScriptParse->ParseScriptText(OLESTR("(new Date()).getTime()"), NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &result, &ei);
        hr = spVBScriptParse->ParseScriptText(OLESTR("Now"), NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &result, &ei);
        hr = spVBScriptParse->ParseScriptText(OLESTR("MsgBox \"Hello World! The current time is: \" & Now"), NULL, NULL, NULL, 0, 0, 0, &result, &ei);
    
        // Cleanup
        spVBScriptParse = NULL;
        spVBScript = NULL;
        spJScriptParse = NULL;
        spJScript = NULL;
        pScriptSite->Release();
        pScriptSite = NULL;
    
        ::CoUninitialize();
        return 0;
    }
    

    A version of the above code can be found here:

    • https://github.com/stephenquan/RunScriptDemo

提交回复
热议问题