当我们的产品发生特定操作时,我们有客户要求调用VBScript函数。 我一直在研究Windows脚本技术,但是我很难find我需要的东西。 希望你们有些人可以帮忙。
我们的产品是一个本地的C ++ Windows产品。 客户将指定一个我们将加载的VBScript文件,并且每当发生特定的事件时,我们都会在VBScript中调用一个特定的函数,并让它做它的事情。 我们可以在脚本的命名空间中提供对象,以便访问有关我们产品的信息。
我在MSDN上发现了关于IActiveScript接口的一些信息,以及一些相关的东西,但是找不到任何实例化实现这个VBScript接口的COM对象的例子。
我知道现在PowerShell可能是一个更好的select,但是我们的客户被困在很多遗留系统中,VBScript就是他们所知道的。
任何帮助,您可以提供(链接或其他),将不胜感激!
看看这个一些示例代码http://support.microsoft.com/kb/221992
有一个msscript.ocx可以帮助你,但如果你可以编写C ++可能比它的价值更麻烦http://msdn.microsoft.com/en-us/magazine/cc302278.aspx
我已经把一个“Hello World”IActiveScript C ++ ATL控制台应用程序放在一起:
CSimpleScriptSite
类
IActiveScriptSite
和IActiveScriptSiteWindow
接口 CoCreateInstance
一个新的IActiveSite
对象
VBScript
和JScript
实例 IActiveSite::SetScriptSite
将IActiveScriptSite
链接到IActiveScriptSite
QueryInterface
获得一个IActiveScriptParse
接口 IActiveScriptParse
执行VBScript
或JScript
代码 JScript
评估一个表达式 VBScript
评估表达式 VBScript
运行一个命令 码:
#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; }
IActiveScript
和相关的接口工作得很好。 我在产品中使用它们与您所描述的完全相同。 一些外部客户编写自己的VBScript和JScript脚本来分析和更新应用程序数据,然后将其发布到数据库中。
使用CoCreateInstance()
来实例化IActiveScript
,就像其他COM对象一样。 然后,您将调用其QueryInterface()
方法来获取用于加载脚本代码片段的IActiveScriptParse
接口,然后更新IActiveScript
的状态以执行代码。
通过实现IDispatch
派生类,然后使用IActiveScript::AddNamedItem()
和IActiveScriptSite::GetItemInfo()
回调将它们传递给引擎,可以将自定义对象添加到脚本中。
在MSDN上有可用的IActiveScript
使用示例。