在C++应用程序中添加VBScript和JScript支持






4.91/5 (23投票s)
介绍 MSSCRIPT.OCX 以及在 C++ 应用程序中调用 JScript 和 VBScript
下载 ScriptDemo 演示项目 - 31 Kb

VBScript 文档
JScript 文档
截图

引言
我一直很惊讶地看到脚本控件 (msscript.ocx) 使用起来非常有趣,但同时,C++ 开发人员在需要使用它时却会做出怎样的反应。 也许扩展名 (.ocx) 使他们觉得这是 Visual Basic! 在本文中,我想消除这些障碍,并为 C++ 开发人员提供一些使用它的新理由。描述
由于 Microsoft 在创建 Windows 脚本技术方面所做的努力,在 VB 和 C++ 应用程序中使用 VBScript 或 JScript 相当简单。 开发人员只需要知道如何使用 Microsoft 脚本 ActiveX 控件 (msscript.ocx) 以及如何将值传递给脚本方法。 因此,我想识别的第一个包装类是CScriptObject
。 此包装器使用起来非常简单,并且提供了您希望在应用程序中使用的大部分功能。 它具有从文件或资源加载脚本(文本数据)的函数,获取方法名称列表,选择脚本语言以及执行函数和语句。 此类不依赖于 MFC,也可以在控制台应用程序中使用。 首先,要调用脚本,重要的是要知道 VBScript 和 JScript 仅处理 VARIANT
参数。 这就是我创建 CSafeArrayHelper
类的原因。 CSafeArray
辅助包装类允许您创建将传递给脚本函数的参数。
class CSafeArrayHelper { public: CSafeArrayHelper(); ~CSafeArrayHelper(); bool Create(VARTYPE vt, UINT cDims, UINT lBound, UINT cCount); bool Destroy(); UINT GetDimension(); bool Attach(LPSAFEARRAY psa); bool AttachFromVariant(VARIANT* pVariant); LPSAFEARRAY Detach(); LPSAFEARRAY GetArray(); bool AccessData(void FAR* FAR* pvData); bool UnaccessData(); bool Lock(); bool Unlock(); bool PutElement(long lIndices, void FAR* vData); bool GetElement(long lIndices, void FAR* vData); VARIANT GetAsVariant(); protected: LPSAFEARRAY m_pSA; private: };它提供与您将要使用的
SAFEARRAY
对象完全相同的功能,但对于我们中的一些人(比如我!),它的用法可能更简单。 如果您想查看封装在 SAFEARRAY
中的数据类型,则函数 GetAsVariant
可能会很有用。 由于 SAFEARRAY
数据类型 (fFeatures
) 未实现,因此该函数无法提供读取所有数据类型的方法。 尽管如此,该函数确实对数据类型进行了猜测。如何使用
首先要使用此控件,我建议您查看 VBScript 和 JScript 的文档,以了解您可以在脚本函数中执行的所有操作。编写脚本函数
假设我们要创建一个简单的函数来转换温度,从华氏温度转换为摄氏温度。在 VBScript 中编写
Function Celsius(fDegrees)
Celsius = (fDegrees - 32) * 5 / 9
End Function
或在 JScript 中编写function Celsius(fDegres)
{
return (fDegres-32)*5/9;
}
要调用此函数,只需将每个参数存储到 VARIANT
中即可。 由于您的函数(方法)可以有多个参数,因此需要 SAFEARRAY
来封装它们。 在后一种情况下,您可能希望通过检查字符串函数的 .length
属性或通过其他方式来查看传递给您的函数的数组的参数计数。function CountParam(aParam)
{
var strPresent = "Parameter is : " + (aParam.length>0 ? "Present": "Not present");
return strPresent;
}
相同的技术也可以在 VBScript 中使用。 这允许您在运行时检测可变长度的参数。 要调用没有参数的函数,将创建一个 SAFERRAY
,但没有参数。调用脚本函数
您的代码可以像这样简单
void CScriptDemoDlg::OnBtnExecute() { CString strParam, strProc; m_ctlParameter.GetWindowText( strParam ); m_ctlFunctions.GetWindowText( strProc ); CSafeArrayHelper sfHelper; try{ _variant_t var; if (strProc.IsEmpty()) sfHelper.Create(VT_VARIANT, 1, 0, 0); // (void) parameter else { sfHelper.Create(VT_VARIANT, 1, 0, 1); // 1 parameter var = _bstr_t(strParam); } sfHelper.PutElement(0, (void*)&var); // parameter1 -> index 0 LPSAFEARRAY sa = sfHelper.GetArray(); _variant_t varRet; if (m_ScriptObj.RunProcedure(strProc, &sa, &varRet)) m_ctlResult.SetWindowText( (LPCTSTR)(_bstr_t(varRet)) ); else { CString strError = m_ScriptObj.GetErrorString(); m_ctlResult.SetWindowText( strError ); } } catch(...) { CString strError = m_ScriptObj.GetErrorString(); m_ctlResult.SetWindowText( strError ); } }
一些想法
您可能想尝试的一些想法。- 您可能希望您的脚本充当插件,一种建议是将资源脚本放入 DLL 中并在运行时加载它(您也可以将其作为应用程序的一部分)。 在这种情况下,您将需要特定的模块相关函数,例如:
InitModule
、ReleaseModule
、btnOK_Click
、btnCancel_Click
、LoadUserData(strUsername)
、SaveUserData(strUserData)
等... 并且您的每个 DLL 都必须实现它们。
- 您可以让您的脚本执行完整的任务,并且您将根据任务加载脚本文件(
CScriptObject
类可以为您加载脚本文件!)。示例:此脚本启动“计算器”程序。
function StartCalc() { var WshShell = new ActiveXObject("WScript.Shell"); var oExec = WshShell.Exec("calc"); WshShell = null; }
- 您可能想要创建比函数调用存在时间更长的 ActiveX 对象
var XML_Obj; function StartModule() { XML_Obj = new ActiveXObject("Msxml.DOMDocument"); XML_Obj.async = false; } function StopModule() { XML_Obj = null; } function LoadSettings(strFilename) { XML_Obj.load(strFilename); }
- 在某些情况下,您可能想要直接执行脚本代码,只需添加代码,不要创建函数...... 试试看吧!
参考文献
Microsoft Windows 脚本控件VBScript 文档
JScript 文档
历史
2002 年 7 月 15 日 - 更新了演示,修复了 VC6 和 VC7 问题