⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scriptenginefactory.cpp

📁 一个很不错的Script解释器
💻 CPP
字号:
// ScriptEngineFactory.cpp: implementation of the ScriptEngineFactory class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ScriptEngineFactory.h"

#include "ExposedObject.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
ScriptEngineFactory* ScriptEngineFactory::m_Instance = NULL;

ScriptEngineFactory::ScriptEngineFactory()
{
	m_iActiveScript           = NULL;
	m_iActiveScriptParse      = NULL;
	m_pScriptDispatch         = NULL;
}

ScriptEngineFactory::~ScriptEngineFactory()
{
}

ScriptEngineFactory* ScriptEngineFactory::Instance()
{
	if (m_Instance == NULL) {
		// Initialize singleton
		m_Instance = new ScriptEngineFactory;
	}

	return m_Instance;
}

BOOL ScriptEngineFactory::HRVerify(HRESULT hr, CString msg)
{
	// If we have a failure, add the error string including
	// hr value to the errormessages array of the scriptsite
	if (FAILED(hr)) {
		CString		str;

		str.Format("COM Error: 0x%08lx\n", hr);
		str += msg;
		m_ScriptSite.m_ErrorMessages.Add(msg);

		return FALSE;
	}

	return TRUE;
}

void ScriptEngineFactory::AddExposedObjectPtr(CString newObjectName, IUnknown* newExposedObject)
{
	USES_CONVERSION;

	HRESULT				hr;
	CString				str;
	ExposedObject*		pObj = NULL;

	// Add to namespace
	hr = m_iActiveScript->AddNamedItem(
		T2OLE(newObjectName), 
		SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE);
	str.Format("Could not add Exposed-Script-Object [%s]", newObjectName);
	HRVerify(hr, str);

	// Save IUnknown ptr ...
	pObj = new ExposedObject;
	pObj->SetExposedObject(newExposedObject);
	pObj->SetObjectName(newObjectName);

	m_ScriptSite.m_ExposedObjects.Add(pObj);
}

void ScriptEngineFactory::InitializeScriptEngine()
{
	int			index;
	HRESULT		hr;
	CLSID		clsid;
	CString		intMessage, extMessage;

	// Initialize the scripting engine, for now we will use VBScript
	// Remove any error messages
	m_ScriptSite.m_ErrorMessages.RemoveAll();

	// Find CLSID
	hr = CLSIDFromProgID(L"VBScript", &clsid);
	if (HRVerify(hr, "Scripting Engine (VBScript.dll) not registered") == FALSE) {
		return;
	}

	// Start VBScript.dll (inproc server)
	hr = CoCreateInstance(
		clsid, NULL, CLSCTX_INPROC_SERVER, 
		IID_IActiveScript, (void**) &m_iActiveScript);
	if (HRVerify(hr, "Scripting Engine (VBScript.dll) not started") == FALSE) {
		return;
	}

	// QueryInterface for IActiveScriptParse
	hr = m_iActiveScript->QueryInterface(
		IID_IActiveScriptParse, (void**) &m_iActiveScriptParse);
	if (HRVerify(hr, "Scripting Engine Parser not available") == FALSE) {
		m_iActiveScript->Release();

		m_iActiveScriptParse = NULL;
		m_iActiveScript      = NULL;
		m_pScriptDispatch    = NULL;

		return;
	}

	// Setup our ScriptSite
	hr = m_iActiveScript->SetScriptSite(&m_ScriptSite);
	if (HRVerify(hr, "Could not host scripting site") == FALSE) {
		m_iActiveScript->Release();
		m_iActiveScriptParse->Release();

		m_iActiveScriptParse = NULL;
		m_iActiveScript      = NULL;
		m_pScriptDispatch    = NULL;

		return;
	}

	hr = m_iActiveScriptParse->InitNew();
	if (HRVerify(hr, "Could not initialize scripting parser") == FALSE) {
		m_iActiveScript->Release();
		m_iActiveScriptParse->Release();

		m_iActiveScriptParse = NULL;
		m_iActiveScript      = NULL;
		m_pScriptDispatch    = NULL;

		return;
	}

	// Initialize m_pScriptDispatch to NULL
	m_pScriptDispatch = NULL;

	// Empty exposed objects array
	for (index = 0; index < m_ScriptSite.m_ExposedObjects.GetSize(); index ++) {
		delete m_ScriptSite.m_ExposedObjects[index];
	}
	m_ScriptSite.m_ExposedObjects.RemoveAll();

	// Set the application main window as ScriptWindow parent
	m_ScriptSite.m_hWnd = ::AfxGetMainWnd()->m_hWnd;
}

BOOL ScriptEngineFactory::RunScript(CString newScript)
{
	HRESULT		hr;
	EXCEPINFO	ei;
	BSTR		pParseText = newScript.AllocSysString();

	// Add script code to the engine
	hr = m_iActiveScriptParse->ParseScriptText(
		pParseText, NULL, NULL, NULL, 0, 0, 0L, NULL, &ei);
	if (HRVerify(hr, "Error parsing script text") == FALSE) {
		hr = m_iActiveScriptParse->Release();
		hr = m_iActiveScript->Release();

		m_iActiveScriptParse = NULL;
		m_iActiveScript      = NULL;
		m_pScriptDispatch    = NULL;

		return FALSE;
	}

	// This will actually run the script
	hr = m_iActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);
	if (HRVerify(hr, "Error running the script") == FALSE) {
		hr = m_iActiveScriptParse->Release();
		hr = m_iActiveScript->Release();

		m_iActiveScriptParse = NULL;
		m_iActiveScript      = NULL;
		m_pScriptDispatch    = NULL;

		return FALSE;
	}

	// This will disconnect the script
	hr = m_iActiveScriptParse->Release();
	hr = m_iActiveScript->Release();

	m_iActiveScriptParse = NULL;
	m_iActiveScript      = NULL;
	m_pScriptDispatch    = NULL;
	
	return TRUE;
}

CStringArray* ScriptEngineFactory::GetErrorMessages()
{
	return &m_ScriptSite.m_ErrorMessages;
}

BOOL ScriptEngineFactory::LoadScript(CString newScript)
{
	HRESULT		hr;
	EXCEPINFO	ei;
	BSTR		pParseText = newScript.AllocSysString();

	// This loads the script and keeps it around for the user
	// to allow to call specific methods in the script
	// Add script code to the engine
	hr = m_iActiveScriptParse->ParseScriptText(
		pParseText, NULL, NULL, NULL, 0, 0, 0L, NULL, &ei);
	if (HRVerify(hr, "Error parsing script text") == FALSE) {
		hr = m_iActiveScriptParse->Release();
		hr = m_iActiveScript->Release();

		m_iActiveScriptParse = NULL;
		m_iActiveScript      = NULL;
		m_pScriptDispatch    = NULL;

		return FALSE;
	}

	// This will actually run the script
	hr = m_iActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);
	if (HRVerify(hr, "Error running the script") == FALSE) {
		hr = m_iActiveScriptParse->Release();
		hr = m_iActiveScript->Release();

		m_iActiveScriptParse = NULL;
		m_iActiveScript      = NULL;
		m_pScriptDispatch    = NULL;

		return FALSE;
	}

	// We need the IDispatch for the script itself
	// to allow to use InvokeHelper
	hr = m_iActiveScript->GetScriptDispatch(0, &m_pScriptDispatch);
	if (HRVerify(hr, "Error getting script dispatch") == FALSE) {
		m_pScriptDispatch = NULL;
		return FALSE;
	}

	// Attach for easy access to InvokeHelper
	// ScriptEngineFactory is actually also derived from COleDispatchDriver,
	// So we can call AttachDispatch to use it's InvokeHelper method
	AttachDispatch(m_pScriptDispatch);

	return TRUE;
}

BOOL ScriptEngineFactory::UnloadScript()
{
	// Release script dispatch pointer from this
	DetachDispatch();

	// Release all interfaces
	if (m_iActiveScriptParse) m_iActiveScriptParse->Release();
	if (m_iActiveScript) m_iActiveScript->Release();
	if (m_pScriptDispatch) m_pScriptDispatch->Release();

	m_iActiveScriptParse = NULL;
	m_iActiveScript      = NULL;
	m_pScriptDispatch    = NULL;

	return TRUE;
}

BOOL ScriptEngineFactory::GetIDOfFunction(CString strFunctionName, DISPID* pID)
{
	// This method retrieves the DISPID to use when
	// calling a method in the loaded script
	// One needs to know how many parameters are used and
	// if there is a return value
	// FALSE is returned when either there is no script loaded,
	// or the method is not there.
	if (m_pScriptDispatch == NULL) {
		return FALSE;
	}

	BSTR pFunctionName = strFunctionName.AllocSysString();
	BOOL bStatus = FALSE;

	bStatus = m_pScriptDispatch->GetIDsOfNames(
		IID_NULL, 
		&pFunctionName, 
		1, 
		LOCALE_SYSTEM_DEFAULT, 
		pID) == S_OK;

	return bStatus;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -