在VC中通过获得IActiveScript接口调用脚本

本文介绍了一个简单的脚本解析实现案例,通过实现IActiveScriptSite和IDispatch接口,作者成功地让应用程序能够运行JScript脚本。代码示例展示了如何创建自定义对象供脚本使用,并解析与执行脚本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 最近由于工作需要,开发的程式需要有二次开发的能力,我想到了脚本解析(PerlScript,JavaScript,VBScript...);经过N多次Google,终于弄了个非常简单的代码;

 

实现了接口IActiveScriptSitet和IDispatch

以下是在类头文件中定义的子类

  1.     BEGIN_INTERFACE_PART(ActiveScriptSite, IActiveScriptSite)
  2.         STDMETHOD(GetLCID)(LCID*) { return E_NOTIMPL; }
  3.         STDMETHOD(GetItemInfo)(LPCOLESTR, DWORD, LPUNKNOWN*, LPTYPEINFO*);
  4.         STDMETHOD(GetDocVersionString)(BSTR*) { return E_NOTIMPL; }
  5.         STDMETHOD(OnScriptTerminate)(const VARIANT*, const EXCEPINFO*) { return S_OK; }
  6.         STDMETHOD(OnStateChange)(SCRIPTSTATE) { return S_OK; }
  7.         STDMETHOD(OnScriptError)(IActiveScriptError*);
  8.         STDMETHOD(OnEnterScript)() { return S_OK; }
  9.         STDMETHOD(OnLeaveScript)() { return S_OK; }
  10.     END_INTERFACE_PART(ActiveScriptSite)
  11.     BEGIN_INTERFACE_PART(MY, IDispatch)
  12.         STDMETHOD(GetTypeInfoCount)(UINT*);
  13.         STDMETHOD(GetTypeInfo)(UINTLCID, ITypeInfo**);
  14.         STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR*, UINTLCID, DISPID*);
  15.         STDMETHOD(Invoke)(DISPID, REFIID, LCIDWORD, DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT *);
  16.         STDMETHOD(GetLCID)(LCID*) { return E_NOTIMPL; }
  17.     END_INTERFACE_PART(MY)

接口类的实现部分,本例中只简单实现了一个函数msg和变量int33。

  1. STDMETHODIMP CApplication1Dlg::XActiveScriptSite::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
  2. {
  3.     if( iid == IID_IUnknown || iid == IID_IActiveScriptSite ){
  4.         *ppvObj = this;
  5.         AddRef();
  6.         return S_OK;
  7.     }
  8.     *ppvObj = NULL;
  9.     return E_NOINTERFACE;
  10. }
  11. STDMETHODIMP CApplication1Dlg::XActiveScriptSite::GetItemInfo(
  12.             /* [in] */ LPCOLESTR pstrName,
  13.             /* [in] */ DWORD dwReturnMask,
  14.             /* [out] */LPUNKNOWN* ppiunkItem,
  15.             /* [out] */LPTYPEINFO* ppti)
  16. {
  17.     if (dwReturnMask & SCRIPTINFO_ITYPEINFO){
  18.         if (!ppti)
  19.             return E_INVALIDARG;
  20.         *ppti = NULL;
  21.     }
  22.     if (dwReturnMask & SCRIPTINFO_IUNKNOWN){
  23.         if (!ppiunkItem)
  24.             return E_INVALIDARG;
  25.         *ppiunkItem = NULL;
  26.     }
  27.     if ( !_wcsicmp( TEXT("MY"), pstrName ) ){
  28.         *ppiunkItem = &pThis->m_xMY;
  29.         (*ppiunkItem)->AddRef();
  30.         return S_OK;
  31.     }
  32.     return E_FAIL;
  33. }
  34. STDMETHODIMP CApplication1Dlg::XActiveScriptSite::OnScriptError( 
  35.             /* [in] */ IActiveScriptError* pse)
  36. {
  37.     EXCEPINFO ei; 
  38.     ULONG     ulLine;
  39.     LONG      ichError; 
  40.     CString strError;
  41.     pse->GetExceptionInfo(&ei);
  42.     pse->GetSourcePosition(NULL, &ulLine, &ichError); 
  43.     
  44.     strError.Format(TEXT("行:/t%d/n字符:/t%d/n错误:/t%s/n代码:/t%x/n来源:/t%s"), ulLine + 1, ichError + 1, (LPCWSTR)ei.bstrDescription, ei.scode, (LPCWSTR)ei.bstrSource );
  45.     AfxMessageBox(strError, MB_ICONSTOP);
  46.     return S_OK;
  47. }
  48. STDMETHODIMP CApplication1Dlg::XMY::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
  49. {
  50.     if ( iid == IID_IUnknown || iid == IID_IDispatch ){
  51.         *ppvObj = this;
  52.         AddRef();
  53.         return S_OK;
  54.     }
  55.     *ppvObj = NULL;
  56.     return E_NOINTERFACE;
  57. }
  58. STDMETHODIMP CApplication1Dlg::XMY::GetTypeInfoCount( 
  59.             /* [out] */ UINT *pctinfo)
  60. {
  61.     return S_OK;
  62. }
  63. STDMETHODIMP CApplication1Dlg::XMY::GetTypeInfo( 
  64.             /* [in] */ UINT iTInfo,
  65.             /* [in] */ LCID lcid,
  66.             /* [out] */ ITypeInfo **ppTInfo)
  67. {
  68.     return S_OK;
  69. }
  70. STDMETHODIMP CApplication1Dlg::XMY::GetIDsOfNames( 
  71.             /* [in] */ REFIID riid,
  72.             /* [size_is][in] */ LPOLESTR *rgszNames,
  73.             /* [in] */ UINT cNames,
  74.             /* [in] */ LCID lcid,
  75.             /* [size_is][out] */ DISPID *rgDispId)
  76. {
  77.     if ( !lstrcmp ( TEXT("msg"), *rgszNames ) ){
  78.         *rgDispId   = 1;
  79.     } else if ( !lstrcmp ( TEXT("int33"), *rgszNames ) ){ 
  80.         *rgDispId   = 2;
  81.     } else {
  82.         return E_NOTIMPL;
  83.     }
  84.     return S_OK;
  85. }
  86. STDMETHODIMP CApplication1Dlg::XMY::Invoke( 
  87.             /* [in] */ DISPID dispIdMember,
  88.             /* [in] */ REFIID riid,
  89.             /* [in] */ LCID lcid,
  90.             /* [in] */ WORD wFlags,
  91.             /* [out][in] */ DISPPARAMS *pDispParams,
  92.             /* [out] */ VARIANT *pVarResult,
  93.             /* [out] */ EXCEPINFO *pExcepInfo,
  94.             /* [out] */ UINT *puArgErr)
  95. {
  96.     switch(dispIdMember){
  97.         case 1:
  98.             if ( pDispParams->cArgs != 1 ) return DISP_E_BADPARAMCOUNT;
  99.             if ( pDispParams->rgvarg[0].vt != VT_BSTR ){ *puArgErr = 0; return DISP_E_TYPEMISMATCH; }
  100.             AfxMessageBox ( pDispParams->rgvarg[0].bstrVal );
  101.             break;
  102.         case 2:
  103.             pVarResult->vt      = VT_I4;
  104.             pVarResult->intVal  = 5000;
  105.             break;
  106.         default:
  107.             return DISP_E_MEMBERNOTFOUND;
  108.     }
  109.     return S_OK;
  110. }

我用了一行简单的JScript脚本代码:

  1. var c=0;var p=2+int33;msg(p.toString());

m_pActiveScript->AddNamedItem 加入自定义的对象,在脚本中可以直接访问这些对象。SCRIPTITEM_GLOBALMEMBERS 标志表示对象在脚本中是个全局对象。

函数m_pActiveScriptParse->ParseScriptText 将脚本代码解析后,调用m_pActiveScript->SetScriptState ( SCRIPTSTATE_STARTED ) 开始执行脚本代码;整个过程非常简单。

  1. CLSID cid;
  2. IActiveScript*      m_pActiveScript         = NULL;
  3. IActiveScriptParse* m_pActiveScriptParse    = NULL;
  4. try {
  5.     HCHECK ( CLSIDFromProgID ( TEXT("JScript"), &cid ) );
  6.     HCHECK ( CoCreateInstance ( cid, NULL, CLSCTX_ALL, IID_IActiveScript, (void **)&m_pActiveScript ) ); 
  7.     HCHECK ( m_pActiveScript->QueryInterface ( IID_IActiveScriptParse, (void **)&m_pActiveScriptParse ) ); 
  8.     HCHECK ( m_pActiveScriptParse->InitNew () );
  9.     HCHECK ( m_pActiveScript->SetScriptSite ( &m_xActiveScriptSite ) );
  10.     HCHECK ( m_pActiveScript->AddNamedItem ( TEXT("MY"), SCRIPTITEM_ISVISIBLE | SCRIPTITEM_GLOBALMEMBERS ) );
  11.     HCHECK ( m_pActiveScriptParse->ParseScriptText ( TEXT("var c=0;var p=2+int33;msg(p.toString());"), NULL, NULL, NULL, 0, 0, 0, NULL, NULL ) );
  12.     HCHECK ( m_pActiveScript->SetScriptState ( SCRIPTSTATE_STARTED ) );
  13.     HCHECK ( m_pActiveScript->Close () );
  14. }
  15. catch (HRESULT hr){
  16.     TRACE("---Script Error: %x ---", hr);
  17. }
  18. if ( m_pActiveScript != NULL ){
  19.     m_pActiveScript->Release ();
  20.     m_pActiveScript = NULL;
  21. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值