我们的客户要求在我们的产品中发生特定操作时调用VBScript函数.我一直在尝试研究Windows Scripting技术,但我很难找到我需要的东西.希望你们中的一些人可以提供帮助.
我们的产品是原生C++ Windows产品.客户将指定我们将加载的VBScript文件,并且每当发生特定事件时,我们将调用VBScript中的特定函数并让它执行其操作.我们可以在脚本的命名空间内提供对象,以便它也可以访问有关我们产品的信息.
我在MSDN上找到了关于IActiveScript接口的一些信息,以及一些相关的东西,但是找不到任何实例化实现VBScript接口的COM对象的例子.
我知道PowerShell现在可能是一个更好的选择,但我们的客户被困在许多遗留系统中,而VBScript就是他们所知道的.
您可以提供的任何帮助(链接或其他)将不胜感激!
Ste*_*uan 12
我已经整理了一个"Hello World"IActiveScript C++ ATL控制台应用程序:
CSimpleScriptSite
类
IActiveScriptSite
接口(强制)IActiveScriptSiteWindow
接口(可选)CoCreateInstance
新IActiveSite
对象
VBScript
和JScript
IActiveSite
到IActiveScriptSite
使用IActiveSite::SetScriptSite
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;
}
Run Code Online (Sandbox Code Playgroud)
IActiveScript
并且相关接口工作得很好。我在我的产品中使用它们的方式与您描述的方式完全相同。一些客户编写自己的 VBScript 和 JScript 脚本来分析和更新应用程序数据,然后再将其发布到数据库。
您可以像实例化任何其他 COM 对象一样来CoCreateInstance()
实例化。IActiveScript
然后,您将调用其QueryInterface()
方法来获取IActiveScriptParse
用于加载脚本代码片段的接口,然后更新 的IActiveScript
状态以执行代码。
您可以通过实现派生类将自定义对象添加到脚本中,然后使用回调IDispatch
将它们传递给引擎。IActiveScript::AddNamedItem()
IActiveScriptSite::GetItemInfo()
MSDN 上有IActiveScript
可用的用法示例。
归档时间: |
|
查看次数: |
10256 次 |
最近记录: |