65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (23投票s)

2002年7月5日

CPOL

3分钟阅读

viewsIcon

427695

downloadIcon

5848

介绍 MSSCRIPT.OCX 以及在 C++ 应用程序中调用 JScript 和 VBScript

下载 ScriptDemo 演示项目 - 31 Kb

截图

引言

我一直很惊讶地看到脚本控件 (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 );
    }
}

一些想法

您可能想尝试的一些想法。
  1. 您可能希望您的脚本充当插件,一种建议是将资源脚本放入 DLL 中并在运行时加载它(您也可以将其作为应用程序的一部分)。 在这种情况下,您将需要特定的模块相关函数,例如:InitModuleReleaseModulebtnOK_ClickbtnCancel_ClickLoadUserData(strUsername)SaveUserData(strUserData) 等... 并且您的每个 DLL 都必须实现它们。

  2. 您可以让您的脚本执行完整的任务,并且您将根据任务加载脚本文件(CScriptObject 类可以为您加载脚本文件!)。

    示例:此脚本启动“计算器”程序。

    function StartCalc()
    {
     var WshShell = new ActiveXObject("WScript.Shell");
     var oExec = WshShell.Exec("calc");
         WshShell = null;
    }
  3. 您可能想要创建比函数调用存在时间更长的 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);
    }
  4. 在某些情况下,您可能想要直接执行脚本代码,只需添加代码,不要创建函数...... 试试看吧!

参考文献

Microsoft Windows 脚本控件
VBScript 文档
JScript 文档

历史

2002 年 7 月 15 日 - 更新了演示,修复了 VC6 和 VC7 问题

© . All rights reserved.