我们的客户要求在我们的产品中发生特定操作时调用VBScript函数.我一直在尝试研究
Windows Scripting技术,但我很难找到我需要的东西.希望你们中的一些人可以提供帮助.
我们的产品是原生C Windows产品.客户将指定我们将加载的VBScript文件,并且每当发生特定事件时,我们将调用VBScript中的特定函数并让它执行其操作.我们可以在脚本的命名空间内提供对象,以便它也可以访问有关我们产品的信息.
我在MSDN上找到了关于IActiveScript接口的一些信息,以及一些相关的东西,但是找不到任何实例化实现VBScript接口的COM对象的例子.
我知道PowerShell现在可能是一个更好的选择,但我们的客户被困在许多遗留系统中,而VBScript就是他们所知道的.
您可以提供的任何帮助(链接或其他)将不胜感激!
解决方法
我已经整理了一个“Hello World”IActiveScript C ATL控制台应用程序:
>定义CSimpleScriptSite类
>实现IActiveScriptSite接口(必填)
>实现IActiveScriptSiteWindow接口(可选)
>使用虚拟存根实现大多数功能的最小实现
>没有错误处理.请参阅MSDN IActiveScriptError.
>使用CoCreateInstance新的IActiveSite对象
>创建VBScript和JScript的实例
>使用IActiveSite :: SetScriptSite将IActiveSite链接到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,SCRIPTTEXT_ISEXPRESSION,&result,&ei); hr = spVBScriptParse->ParseScriptText(OLESTR("Now"),&ei); hr = spVBScriptParse->ParseScriptText(OLESTR("MsgBox \"Hello World! The current time is: \" & Now"),&ei); // Cleanup spVBScriptParse = NULL; spVBScript = NULL; spJScriptParse = NULL; spJScript = NULL; pScriptSite->Release(); pScriptSite = NULL; ::CoUninitialize(); return 0; }