Script.h
#pragma once
#include <xstring>
#include <list>
#import "msscript.ocx" no_namespace
#define LANGUAGE_DEFAULT _T("JScript")
#define RT_SCRIPT _T("SCRIPT")
#define LANGUAGE_NAME_LEN 40
#define ERROR_DESC_LEN 256
using namespace std;
#ifndef _UNICODE
typedef list<string> stl_string_list;
#else
typedef list<wstring> stl_string_list;
#endif
class CScript
{
public:
CScript(void);
~CScript(void);
public:
bool LoadScript(__in LPCTSTR szFilename); //通过路径加载脚本文件
bool LoadScriptResource(__in LPCTSTR lpName, __in LPCTSTR lpType,__in HINSTANCE hInstance); //通过资源加载脚本文件
LPCTSTR GetLanguage(); //获取脚本语言
void SetLanguage(__in LPCTSTR szLanguage); //设置脚本语言
int GetMethodsCount() const; //获取函数个数
LPCTSTR GetNameAt(__in int index); //获取对应索引的函数名
_variant_t ExecFunc(__in LPCTSTR lpfunc ,__in _variant_t varParam);//执行函数
LPCTSTR ExecFunc(__in LPCTSTR lpfunc ,__in LPCTSTR lpParam);//执行函数
private:
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();
public:
void Reset();
bool AddScript(LPCTSTR szCode);
LPCTSTR GetErrorString();
bool ExecuteStatement(LPCTSTR szStatement);
bool RunProcedure(LPCTSTR szProcName, SAFEARRAY** saParameters, VARIANT* varRet);
private:
void CommonConstruct();
bool GetMethodsName();
LPCTSTR GetScriptFunction(LPCTSTR name);
LPSAFEARRAY m_pSA;
IScriptControlPtr m_pScript; // The one and only script control
stl_string_list m_FunctionList; // Function list
TCHAR m_szLanguage[LANGUAGE_NAME_LEN+1]; // Current language
TCHAR m_szError[ERROR_DESC_LEN+1]; // Description error
};
Script.cpp
#include "StdAfx.h"
#include "Script.h"
CScript::CScript(void)
{
m_pSA = NULL;
memset(m_szError,0,ERROR_DESC_LEN);
memset(m_szLanguage,0,LANGUAGE_NAME_LEN);
if (!AfxOleInit())
{
return;
}
CommonConstruct();
}
CScript::~CScript(void)
{
m_pScript = NULL;
Destroy();
}
void CScript::CommonConstruct()
{
HRESULT hr = m_pScript.CreateInstance(__uuidof(ScriptControl));
_com_util::CheckError( hr ); // will throw an exception if failed
// will not come here if exception
_tcscpy_s(m_szLanguage,LANGUAGE_NAME_LEN+1, LANGUAGE_DEFAULT);
m_pScript->PutAllowUI( VARIANT_FALSE );
m_pScript->PutLanguage( _bstr_t(m_szLanguage ));
}
LPCTSTR CScript::GetLanguage()
{
return m_szLanguage;
}
void CScript::SetLanguage(LPCTSTR szLanguage)
{
_tcscpy_s(m_szLanguage,LANGUAGE_NAME_LEN+1, szLanguage);
if (m_pScript != NULL)
{
m_pScript->PutLanguage( _bstr_t( szLanguage ) );
m_pScript->Reset();
m_FunctionList.clear();
}
}
bool CScript::Create(VARTYPE vt, UINT cDims, UINT lBound, UINT cCount)
{
Destroy();
if (cDims == 1) // this is somewhat faster...
m_pSA = SafeArrayCreateVector(vt, lBound, cCount);
else
{
SAFEARRAYBOUND rgsabound[1] = { 0 };
rgsabound[0].lLbound = lBound;
rgsabound[0].cElements = cCount;
m_pSA = SafeArrayCreate(vt, cDims, rgsabound);
}
return (m_pSA != NULL);
}
bool CScript::Destroy()
{
if (NULL != m_pSA)
{
// Maybe the object is locked!
if (SUCCEEDED(SafeArrayDestroy( m_pSA )))
m_pSA = NULL;
}
return (m_pSA == NULL);
}
LPSAFEARRAY CScript::GetArray()
{
return m_pSA;
}
UINT CScript::GetDimension()
{
UINT uDim = 0;
if (NULL != m_pSA)
uDim = SafeArrayGetDim( m_pSA );
return uDim;
}
bool CScript::Attach(LPSAFEARRAY psa)
{
if (NULL != psa) // prevent 'destroy' for null pointer
{
Destroy();
m_pSA = psa;
return true;
}
return false;
}
LPSAFEARRAY CScript::Detach()
{
if (NULL == m_pSA)
return NULL;
LPSAFEARRAY psa = m_pSA;
m_pSA = NULL;
return psa;
}
bool CScript::AttachFromVariant(VARIANT* pVariant)
{
if (NULL != pVariant)
{
if (pVariant->vt & VT_ARRAY)
{
LPSAFEARRAY psa = pVariant->parray;
if (pVariant->vt & VT_BYREF) // VB use this...
psa = *pVariant->pparray;
return Attach( psa );
}
}
return false;
}
VARIANT CScript::GetAsVariant()
{
VARIANT var;
VariantClear(&var);
if (NULL != m_pSA)
{
var.vt = VT_ARRAY|VT_BYREF;
var.pparray = &m_pSA;
USHORT fFeatures = m_pSA->fFeatures;
LONG cbElements = m_pSA->cbElements;
if (fFeatures & FADF_BSTR)
var.vt |= VT_BSTR;
else if (fFeatures & FADF_UNKNOWN)
var.vt |= VT_UNKNOWN;
else if (fFeatures & FADF_DISPATCH)
var.vt |= VT_DISPATCH;
else if (fFeatures & FADF_VARIANT)
var.vt |= VT_VARIANT;
else if (fFeatures & FADF_RECORD)
var.vt |= VT_RECORD;
else if (fFeatures & FADF_HAVEVARTYPE)
{
// these are just guess based on size of element, may not be accurated...
if (sizeof(char) == cbElements) // 1 byte
var.vt |= VT_UI1;
else if (sizeof(short) == cbElements) // 2 bytes
var.vt |= VT_UI2;
else if (sizeof(long) == cbElements) // 4 bytes -- or float (VT_R4)
var.vt |= VT_UI4;
else if (sizeof(double) == cbElements) // 8 bytes -- or Currency (VT_CY)
var.vt |= VT_R8;
}
}
return var;
}
bool CScript::AccessData(void FAR* FAR* pvData)
{
if (NULL != m_pSA && NULL != pvData)
{
return (SafeArrayAccessData(m_pSA, pvData) == S_OK);
}
return false;
}
bool CScript::UnaccessData()
{
if (NULL != m_pSA)
{
return (SafeArrayUnaccessData(m_pSA) == S_OK);
}
return false;
}
bool CScript::Lock()
{
if (NULL != m_pSA)
{
return (SafeArrayLock(m_pSA) == S_OK);
}
return false;
}
bool CScript::Unlock()
{
if (NULL != m_pSA)
{
return (SafeArrayUnlock(m_pSA) == S_OK);
}
return false;
}
bool CScript::PutElement(long lIndices, void FAR* vData)
{
if (NULL != m_pSA)
{
return (SafeArrayPutElement(m_pSA, &lIndices, vData) == S_OK);
}
return false;
}
bool CScript::GetElement(long lIndices, void FAR* vData)
{
if (NULL != m_pSA)
{
return (SafeArrayGetElement(m_pSA, &lIndices, vData) == S_OK);
}
return false;
}
int CScript::GetMethodsCount() const
{
return m_FunctionList.size();
}
LPCTSTR CScript::GetNameAt(int index)
{
if( index >= 0 && index < (int)m_FunctionList.size())
{
stl_string_list::iterator iter = m_FunctionList.begin();
while( index > 0)
{
iter++;
index--;
}
return (*iter).c_str();
}
return TEXT("");
}
void CScript::Reset()
{
if (m_pScript != NULL)
{
m_pScript->Reset();
// empty list...
m_FunctionList.clear();
}
}
LPCTSTR CScript::GetErrorString()
{
m_szError[0] = 0;
if (m_pScript != NULL)
{
try{
IScriptErrorPtr pError = m_pScript->GetError();
if (pError != NULL)
{
_bstr_t desc = _bstr_t("Error: ") + pError->GetDescription() + _bstr_t(", ");
desc += pError->GetText() + _bstr_t("; in line ");
desc += _bstr_t(pError->GetLine());
int count = __min(desc.length(), ERROR_DESC_LEN); // string may be truncated...
_tcsncpy_s(m_szError, (LPCTSTR) desc, count);
m_szError[count] = 0;
pError->Clear();
}
}
catch(_com_error& e)
{
TRACE( (LPSTR)e.Description() );
TRACE( (LPSTR)"\n" );
}
}
return m_szError;
}
bool CScript::GetMethodsName()
{
bool bResult = false;
if (m_pScript != NULL)
{
IScriptProcedureCollectionPtr pIProcedures = m_pScript->GetProcedures();
// empty list...
m_FunctionList.clear();
try{
long count = pIProcedures->GetCount();
for(long index=1; index <= count; index++)
{
IScriptProcedurePtr pIProcPtr = pIProcedures->GetItem( _variant_t(index) );
_bstr_t name = pIProcPtr->GetName();
m_FunctionList.insert(m_FunctionList.end(), (LPCTSTR) name );
pIProcPtr = NULL;
}
bResult = true;
}
catch(...)
{
// Just catch the exception, call GetErrorString()
// to retreive last error
}
pIProcedures = NULL;
}
return bResult;
}
LPCTSTR CScript::GetScriptFunction(LPCTSTR szName)
{
stl_string_list::iterator iter = m_FunctionList.begin();
while( iter != m_FunctionList.end() )
{
if ((*iter).compare(szName) == 0)
return (*iter).c_str();
iter++;
}
return TEXT("");
}
bool CScript::LoadScriptResource(LPCTSTR lpName, LPCTSTR lpType, HINSTANCE hInstance )
{
try{
if (m_pScript)
{
HRSRC res = ::FindResource(hInstance, lpName, lpType);
ASSERT( res != NULL);
BYTE* pbytes = (BYTE*) LockResource(LoadResource(hInstance, res ));
ASSERT( pbytes != NULL);
_bstr_t strCode = (LPCSTR) (pbytes);
m_pScript->AddCode( strCode );
GetMethodsName();
return true;
}
}
catch(...)
{
// Just catch the exception, call GetErrorString()
// to retreive last error
}
return false;
}
bool CScript::LoadScript(LPCTSTR szFilename)
{
HANDLE hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD dwSize = GetFileSize(hFile, NULL);
if (0xFFFFFFFF != dwSize)
{
BYTE* pbytes = (BYTE*) GlobalAlloc(GPTR, dwSize+1);
if (pbytes != NULL)
{
DWORD dwRead = 0;
bool bResult = false;
if (ReadFile(hFile, pbytes, dwSize, &dwRead, NULL))
{
try{
if (m_pScript)
{
_bstr_t strCode = (LPCSTR) (pbytes);
m_pScript->AddCode( strCode );
GetMethodsName();
bResult = true;
}
}
catch(...)
{
// Just catch the exception, call GetErrorString()
// to retreive last error
}
GlobalFree( (HGLOBAL) pbytes);
CloseHandle(hFile);
return bResult;
}
GlobalFree( (HGLOBAL) pbytes);
}
}
CloseHandle(hFile);
return false;
}
return false;
}
bool CScript::AddScript(LPCTSTR szCode)
{
try {
if (m_pScript != NULL)
{
ULONG ref = m_pScript->AddRef();
_bstr_t strCode = szCode;
m_pScript->AddCode( strCode );
GetMethodsName();
ref = m_pScript->Release();
return true;
}
}
catch(...)
{
// Just catch the exception, call GetErrorString()
// to retreive last error
ULONG ref = m_pScript->Release();
}
return false;
}
bool CScript::ExecuteStatement(LPCTSTR szStatement)
{
try {
if (m_pScript != NULL)
{
ULONG ref = m_pScript->AddRef();
m_pScript->ExecuteStatement( _bstr_t(szStatement) );
ref = m_pScript->Release();
return true;
}
}
catch(...)
{
// Just catch the exception, call GetErrorString()
// to retreive last error
ULONG ref = m_pScript->Release();
}
return false;
}
bool CScript::RunProcedure(LPCTSTR szProcName, SAFEARRAY** saParameters, VARIANT* varRet)
{
// required argument
ASSERT( saParameters != NULL);
ASSERT( varRet != NULL);
try {
if (m_pScript != NULL)
{
ULONG ref = m_pScript->AddRef();
bool bResult = false;
_bstr_t szFunc = GetScriptFunction(szProcName);
if (szFunc.length() > 0)
{
*varRet = m_pScript->Run(szFunc, saParameters);
bResult = true;
}
ref = m_pScript->Release();
return bResult;
}
}
catch(...)
{
// Just catch the exception, call GetErrorString()
// to retreive last error
ULONG ref = m_pScript->Release();
}
return false;
}
_variant_t CScript::ExecFunc(LPCTSTR lpfunc ,_variant_t varParam)
{
try{
_variant_t var;
if (_tcsclen(lpfunc) <= 0)
this->Create(VT_VARIANT, 1, 0, 0);
else
{
this->Create(VT_VARIANT, 1, 0, 1);
var = varParam;
}
this->PutElement(0, (void*)&var);// parameter1 -> index 0
LPSAFEARRAY sa = this->GetArray();
_variant_t varRet;
if (RunProcedure(lpfunc, &sa, &varRet))
return varRet;
else
{
return _bstr_t(GetErrorString());
}
}
catch(...)
{
return _bstr_t(GetErrorString());
}
}
LPCTSTR CScript::ExecFunc(__in LPCTSTR lpfunc ,__in LPCTSTR lpParam)
{
try{
_variant_t var;
if (_tcsclen(lpfunc) <= 0)
this->Create(VT_VARIANT, 1, 0, 0);
else
{
this->Create(VT_VARIANT, 1, 0, 1);
var = _bstr_t(lpParam);
}
this->PutElement(0, (void*)&var);// parameter1 -> index 0
LPSAFEARRAY sa = this->GetArray();
_variant_t varRet;
if (RunProcedure(lpfunc, &sa, &varRet))
return (LPCTSTR)_bstr_t(varRet);
else
{
return GetErrorString();
}
}
catch(...)
{
return GetErrorString();
}
}
调用sample:
CScript script;
CString strpath = _T("C:\\encoding.js");
script.LoadScript(strpath);
CString strRet = script.ExecFunc(_T("encoding"),_T("测试项目"));
JS代码:
function encoding(str)
{
return encodeURI(str);
}
运行结果如下:
strRet = "%E6%B5%8B%E8%AF%95%E9%A1%B9%E7%9B%AE";