Click here to Skip to main content
11,436,156 members (65,356 online)
Click here to Skip to main content

Adding VBScript and JScript support in your C++ applications

, 14 Jul 2002 CPOL
Rate this:
Please Sign up or sign in to vote.
Introduce to MSSCRIPT.OCX and calling JScript and VBScript in your C++ Application
Download ScriptDemo Demo Project - 31 Kb

ScreenShots

Introduction

I am always amazed to see how the script control (msscript.ocx) is fun to use and at the same time how C++ developers reacted when it's time to use. Maybe the extension (.ocx) make them feel, it's visual basic! In this article, I would like to remove those frontiers and give some new reasons for C++ developers to use it.

Description

To use either VBScript or JScript is fairly simple in a VB and C++ Application thanks to Microsoft's development efforts to create Windows Scripting technology. A developer only needs to know how to use the Microsoft Scripting ActiveX control (msscript.ocx) and how to pass value to a script method. For this reason, the first wrapper class that I want to identify is the CScriptObject. This wrapper is very simple to use and it provides most of the functionality that you will want to use in your application. It has a function to load script (text data) from a file or resource, get a list of methods name, selecting script language and to the execute function and statement. This class has no dependencies on MFC and can also be used in a console application. 

First of all to call a script it is important to know that VBScript and JScript deal only with VARIANT parameters. This is the reason I created the CSafeArrayHelper class. The CSafeArray helper wrapper class allows you to create parameters that you will pass to your script function.

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:
};
It provides the exact same features that you will want to use with SAFEARRAY object but its usage may be simpler for some of us (like me!). The function GetAsVariant may be useful in case when you want to view the type of data that was encapsulated in your SAFEARRAY. This function could not provide ways to read all data types since the SAFEARRAY Data type (fFeatures) didn't implement it. Nonetheless to say, this function do a guess on the data types.

How to use

First to use this control, I will recommend you to take a look at the documentation for VBScript and JScript to know all you can do within your script function.

Writing a Script function

Let's say we want to create a simple function to convert temperature from Fahrenheit to Celsius.

In VBScript write:

Function Celsius(fDegrees)
   Celsius = (fDegrees - 32) * 5 / 9
End Function
or in JScript write:
function Celsius(fDegres)
{
   return (fDegres-32)*5/9;
}
To call this function, one only needs to store each parameter into VARIANT. Since your function (method) can have more than one parameter, a SAFEARRAY is needed to encapsulated them. In that latter case, you may want to view the parameter count for the array passed to your function by checking the .length property for string function or by some other means.
function CountParam(aParam)
{
    var strPresent = "Parameter is : " + (aParam.length>0 ? "Present": "Not present");
    return strPresent;
}
The same technique may be used in VBScript. This allows you to detect variable length argument at run time. To call a function without argument, a SAFERRAY is created but without parameter.

Calling a Script function

Your code can be as easy as this:

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 );
    }
}

Some Ideas

Some of the ideas that you may want to try.
  1. You may want to have your script acts like a plugin, one suggestion is to have a resource script into a DLL and loads it at runtime (you may also have it part of your application). In that case, you will want to have specific module-related function, like: InitModule, ReleaseModule, btnOK_Click, btnCancel_Click, LoadUserData(strUsername), SaveUserData(strUserData), etc... and each of your DLL will have to implement them.

  2. You may have your script to do a complete task and you will load the script file based on the task (the CScriptObject class can load a script file for you!).

    Example: This script starts the "Calculator" program.

    function StartCalc()
    {
     var WshShell = new ActiveXObject("WScript.Shell");
     var oExec = WshShell.Exec("calc");
         WshShell = null;
    }
  3. You may want to create ActiveX object that lives longer than for a function call:
    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. There are cases that you may want to execute the script code directly, just add the code, do not create a function...try it for fun!

References

Microsoft Windows Script Control
VBScript Documentation
JScript Documentation

History

15 July 2002 - updated demo fixed VC6 and VC7 issues

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ernest Laurentin
Software Developer (Senior)
United States United States
Ernest is a multi-discipline software engineer.
Skilled at software design and development for all Windows platforms.
-
MCSD (C#, .NET)
Interests: User Interface, GDI/GDI+, Scripting, Android, iOS, Windows Mobile.
Programming Skills: C/C++, C#, Java (Android), VB and ASP.NET.

I hope you will enjoy my contributions.

Comments and Discussions

 
Questionif i have four parameters what should do ?how to pass four parameters? Pin
Member 1151108916-Mar-15 23:29
memberMember 1151108916-Mar-15 23:29 
QuestionWindow object Pin
Eugene Ochakovsky3-Jun-13 0:11
memberEugene Ochakovsky3-Jun-13 0:11 
AnswerRe: Window object Pin
Ernest Laurentin9-Jun-13 19:52
memberErnest Laurentin9-Jun-13 19:52 
Look at my other article: "ScriptRunner Application"
Questionmsscript.ocx is not supported on Windows x64 Pin
fsandner6-Oct-11 21:41
memberfsandner6-Oct-11 21:41 
GeneralVisual Basic App Pin
malfaro25-Feb-11 16:09
membermalfaro25-Feb-11 16:09 
GeneralAn error happened when the application existed Pin
shengberlin24-Sep-09 3:53
membershengberlin24-Sep-09 3:53 
GeneralDestroying the SAFEARRAY after an error Pin
Ralf Patzig1-Jul-08 23:08
memberRalf Patzig1-Jul-08 23:08 
GeneralRe: Destroying the SAFEARRAY after an error Pin
Ernest Laurentin2-Jul-08 5:02
memberErnest Laurentin2-Jul-08 5:02 
GeneralScript Time Out Pin
ynotyon25-Jun-08 8:44
memberynotyon25-Jun-08 8:44 
GeneralLoadScript problem in a visual C++ thread Pin
victor domingo reguant15-Oct-07 7:06
membervictor domingo reguant15-Oct-07 7:06 
QuestionLoadScript problem in VC++ thread Pin
victor domingo reguant15-Oct-07 7:03
membervictor domingo reguant15-Oct-07 7:03 
GeneralMSScript reset trouble. Pin
k01dunn29-Aug-07 5:33
memberk01dunn29-Aug-07 5:33 
General2 Parameters Again Pin
Peter Weyzen28-Apr-07 10:52
memberPeter Weyzen28-Apr-07 10:52 
GeneralRe: 2 Parameters Again Pin
Ernest Laurentin28-Apr-07 12:12
memberErnest Laurentin28-Apr-07 12:12 
GeneralRe: 2 Parameters Again Pin
Peter Weyzen30-Apr-07 12:38
memberPeter Weyzen30-Apr-07 12:38 
QuestionHow can I use AddObject and use it. Pin
coronys13-Dec-06 5:38
membercoronys13-Dec-06 5:38 
GeneralDetermine function parameters Pin
coronys7-Dec-06 0:09
membercoronys7-Dec-06 0:09 
AnswerRe: Determine function parameters Pin
Ernest Laurentin7-Dec-06 16:12
memberErnest Laurentin7-Dec-06 16:12 
GeneralRe: Determine function parameters Pin
coronys7-Dec-06 20:01
membercoronys7-Dec-06 20:01 
GeneralGet the source line number Pin
AKSIVAKUMAR16-Oct-06 22:08
memberAKSIVAKUMAR16-Oct-06 22:08 
GeneralRe: Get the source line number Pin
AKSIVAKUMAR18-Oct-06 0:49
memberAKSIVAKUMAR18-Oct-06 0:49 
GeneralProblems with msscript.tlh Pin
xricon21-Oct-05 11:00
memberxricon21-Oct-05 11:00 
GeneralRe: Problems with msscript.tlh Pin
Anonymous21-Oct-05 14:45
sussAnonymous21-Oct-05 14:45 
GeneralRe: Problems with msscript.tlh Pin
Anonymous24-Oct-05 5:13
sussAnonymous24-Oct-05 5:13 
QuestionPassing "binary" data to script... Pin
SonicMouser11-Oct-05 4:22
memberSonicMouser11-Oct-05 4:22 
AnswerRe: Passing "binary" data to script... Pin
SonicMouser11-Oct-05 18:06
memberSonicMouser11-Oct-05 18:06 
Questioncall application method? Pin
yanba4-Oct-05 17:53
memberyanba4-Oct-05 17:53 
AnswerRe: call application method? Pin
cederron1-Mar-07 13:50
membercederron1-Mar-07 13:50 
GeneralParameter names Pin
duronebis29-Sep-05 8:59
memberduronebis29-Sep-05 8:59 
GeneralScriptObject not instantiated Pin
Mouad21-Jul-05 0:19
sussMouad21-Jul-05 0:19 
GeneralRe: ScriptObject not instantiated Pin
Ernest Laurentin21-Jul-05 16:27
memberErnest Laurentin21-Jul-05 16:27 
GeneralRe: ScriptObject not instantiated Pin
Anonymous22-Jul-05 1:21
sussAnonymous22-Jul-05 1:21 
GeneralCreate an ActiveX object in VC++ Pin
Anonymous27-Apr-05 11:28
sussAnonymous27-Apr-05 11:28 
GeneralCreate an ActiveX object in VC++ Pin
Anonymous13-Apr-05 10:43
memberAnonymous13-Apr-05 10:43 
GeneralRe: Create an ActiveX object in VC++ Pin
Ernest Laurentin13-Apr-05 14:12
memberErnest Laurentin13-Apr-05 14:12 
GeneralCalling VBScript from standalone code Pin
grantepalmer4-Apr-05 18:52
membergrantepalmer4-Apr-05 18:52 
QuestionHow can I receive a VBScript integer array or how can i change the type of the VARIANT parameter Pin
Nohemi21-Dec-04 7:36
memberNohemi21-Dec-04 7:36 
AnswerRe: How can I receive a VBScript integer array or how can i change the type of the VARIANT parameter Pin
kamel28-Aug-06 6:15
memberkamel28-Aug-06 6:15 
GeneralTwo parameters Pin
fpdeguzman5-Feb-04 22:55
memberfpdeguzman5-Feb-04 22:55 
GeneralRe: Two parameters Pin
Rizwan_Khalid10-Jul-04 4:21
memberRizwan_Khalid10-Jul-04 4:21 
GeneralRe: Two parameters Pin
Anonymous12-Jul-04 16:33
sussAnonymous12-Jul-04 16:33 
GeneralRe: Two parameters Pin
fpdeguzman12-Jul-04 16:38
memberfpdeguzman12-Jul-04 16:38 
GeneralGraphical Interface Pin
MicaS26-Jan-04 6:32
memberMicaS26-Jan-04 6:32 
GeneralRe: Graphical Interface Pin
Ernest Laurentin26-Jan-04 21:22
memberErnest Laurentin26-Jan-04 21:22 
GeneralCompile prob (release mode only) Pin
Jason Hattingh27-Dec-03 5:01
memberJason Hattingh27-Dec-03 5:01 
QuestionCan it run encoded script ? Pin
wangniu8-Dec-03 3:53
memberwangniu8-Dec-03 3:53 
QuestionHow do I receive a VBScript array??? Pin
johannks26-Nov-03 23:43
memberjohannks26-Nov-03 23:43 
GeneralAutomation Server Support Pin
zkrr0110-Oct-03 10:40
memberzkrr0110-Oct-03 10:40 
GeneralAlert & Prompt Pin
DJMystic28-Aug-03 10:05
memberDJMystic28-Aug-03 10:05 
GeneralRe: Alert & Prompt Pin
Ernest Laurentin30-Aug-03 8:35
memberErnest Laurentin30-Aug-03 8:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150428.2 | Last Updated 15 Jul 2002
Article Copyright 2002 by Ernest Laurentin
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid