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

后端 未结 2 1657
时光取名叫无心
时光取名叫无心 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条回答
  • 2020-12-03 12:55

    IActiveScript and related interfaces work very well. I use them in my product exactly the same way you have described. Some of out customers write their own VBScript and JScript scripts to analyze and update application data before it gets posted to a database.

    You use CoCreateInstance() to instantiate IActiveScript, like you would any other COM object. You would then call its QueryInterface() method to obtain an IActiveScriptParse interface for loading snippets of scripting code, and then you update the IActiveScript's state to execute the code.

    You can add custom objects to the script by implementing IDispatch-derived classes and then passing them to the engine using IActiveScript::AddNamedItem() and an IActiveScriptSite::GetItemInfo() callback.

    There are examples of IActiveScript usage available on MSDN.

    0 讨论(0)
  • 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 <atlbase.h>
    #include <activscp.h>
    
    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<IActiveScript> spJScript;
        CComPtr<IActiveScriptParse> spJScriptParse;
        hr = spJScript.CoCreateInstance(OLESTR("JScript"));
        hr = spJScript->SetScriptSite(pScriptSite);
        hr = spJScript->QueryInterface(&spJScriptParse);
        hr = spJScriptParse->InitNew();
        CComPtr<IActiveScript> spVBScript;
        CComPtr<IActiveScriptParse> 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
    0 讨论(0)
提交回复
热议问题