我用 ATL 创建了一个 ActiveX 控件, 实现了IActiveScriptSite 接口以及Connection Point。
脚本执行没有问题,能调我定义的接口方法,但是脚本不能响应事件通知。
但如果我编写一个HTML,在HTML 创建该ActiveX,事件响应又是正常的。
有人知道是什么地方出问题了吗?详细信息:
我在 ActiveX 中创建了 IActiveScript 对象 spAS
spAS->AddNamedItem( "Test", SCRIPTITEM_ISSOURCE | SCRIPTITEM_ISVISIBLE );
该 ActiveX 会定时触发一个OnTimer事件
我的VBScript脚本是这样编写的:
Sub Test_OnTimer( nID ) 弹出一个对话框End Sub 但这个对话框始终弹不出来
脚本执行没有问题,能调我定义的接口方法,但是脚本不能响应事件通知。
但如果我编写一个HTML,在HTML 创建该ActiveX,事件响应又是正常的。
有人知道是什么地方出问题了吗?详细信息:
我在 ActiveX 中创建了 IActiveScript 对象 spAS
spAS->AddNamedItem( "Test", SCRIPTITEM_ISSOURCE | SCRIPTITEM_ISVISIBLE );
该 ActiveX 会定时触发一个OnTimer事件
我的VBScript脚本是这样编写的:
Sub Test_OnTimer( nID ) 弹出一个对话框End Sub 但这个对话框始终弹不出来
#include "stdafx.h"
#include "MyScript.h"
#include "psapi.h"
#pragma comment(lib, "Psapi.lib")
// CMyScript
// IActiveScriptSite
STDMETHODIMP CMyScript::GetLCID(/*[out]*/ LCID *plcid)
{
return E_NOTIMPL;
}STDMETHODIMP CMyScript::GetItemInfo(/*[in]*/ LPCOLESTR pstrName,
/*[in]*/ DWORD dwReturnMask,
/*[out]*/ IUnknown **ppunkItem,
/*[out]*/ ITypeInfo **ppTypeInfo)
{
if(ppTypeInfo)
{
*ppTypeInfo = NULL; if(dwReturnMask & SCRIPTINFO_ITYPEINFO)
{
CComPtr< ITypeLib > sptLib;
::LoadTypeLib( L"MyScriptProject.tlb", &sptLib ); //装载自身的类型库
if( sptLib )
{
sptLib->GetTypeInfo( 0, ppTypeInfo );
}
}
} if(ppunkItem)
{
*ppunkItem = NULL; if(dwReturnMask & SCRIPTINFO_IUNKNOWN)
{
if ( m_strObjName.Compare(pstrName ) == 0 )
{
ControlQueryInterface( IID_IUnknown, (LPVOID *)ppunkItem );
}
}
} return S_OK;
}STDMETHODIMP CMyScript::GetDocVersionString(/*[out]*/ BSTR *pbstrVersionString)
{
return E_NOTIMPL;
}STDMETHODIMP CMyScript::OnScriptTerminate(/*[in]*/ const VARIANT *pvarResult, /*[in]*/ const EXCEPINFO *pexcepinfo)
{
return S_OK;
}STDMETHODIMP CMyScript::OnStateChange(/*[in]*/ SCRIPTSTATE ssScriptState)
{
return S_OK;
}STDMETHODIMP CMyScript::OnScriptError(/*[in]*/ IActiveScriptError *pase)
{
CComBSTR strErr;
CComBSTR strMsg;
HRESULT hr = pase->GetSourceLineText( &strErr );
if( FAILED(hr) || !strErr.Length() )
{
strMsg = L"未知错误";
}
else
{
strMsg = L"语法错误: ";
strMsg.AppendBSTR( strErr );
}// Fire_ScriptErr( msg ); return S_OK;
}STDMETHODIMP CMyScript::OnEnterScript(void)
{
return S_OK;
}STDMETHODIMP CMyScript::OnLeaveScript(void)
{
return S_OK;
}
STDMETHODIMP CMyScript::ExecuteScript(BSTR bstrScript, VARIANT_BOOL* bSuccess)
{
// TODO: Add your implementation code here HRESULT hr = S_FALSE;
*bSuccess = VARIANT_FALSE; try
{
if ( FAILED( CloseScript() ) )
{
throw ( L"CloseScript failed!" );
}
m_spAS.CoCreateInstance( L"JavaScript"); if ( m_spAS == NULL )
{
throw (L"Can not create instance of IActiveScript");
}
//
m_spAS->SetScriptSite( this );
if ( FAILED( m_spAS->AddNamedItem( m_strObjName, SCRIPTITEM_ISSOURCE | SCRIPTITEM_ISVISIBLE ) ) )
{
throw ( L"IActiveScript AddNamedItem failed!" );
} CComQIPtr<IActiveScriptParse> spASP(m_spAS);
if ( FAILED( spASP->InitNew() ) )
{
throw( L"IActiveScriptParse InitNew failed!" );
} EXCEPINFO ei;
if ( FAILED( spASP->ParseScriptText( bstrScript, m_strObjName, NULL, NULL, 0, 0, 0, NULL, &ei ) ) )
{
throw ( L"IActiveScriptParse ParseScriptText failed!" );
} m_spAS->SetScriptState( SCRIPTSTATE_CONNECTED);
*bSuccess = VARIANT_TRUE;
hr = S_OK; }
catch( LPCWSTR lpszDesc)
{
CString strDesc = lpszDesc;
*bSuccess = VARIANT_FALSE;
hr = S_FALSE;; }
catch(...)
{
*bSuccess = VARIANT_FALSE;
hr = S_FALSE; } return hr;
}LRESULT CMyScript::OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// TODO: Add your message handler code here and/or call default return 0;
}STDMETHODIMP CMyScript::CloseScript(void)
{
// TODO: Add your implementation code here if ( m_spAS == NULL )
{
}
else
{
m_spAS->SetScriptState( SCRIPTSTATE_DISCONNECTED );
m_spAS->Close();
m_spAS.Release();
}
return S_OK;
}STDMETHODIMP CMyScript::MyShowMsg(BSTR bstrText, BSTR bstrTitle, USHORT uType, LONG* bRet)
{
// TODO: Add your implementation code here
*bRet = ::MessageBox( NULL, CString(bstrText), CString(bstrTitle), MB_OK ); return S_OK;
}STDMETHODIMP CMyScript::MyProcessExist(BSTR bstrExepath, VARIANT_BOOL* bExist)
{
// TODO: Add your implementation code here * bExist = FALSE; DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i = 0; if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return S_FALSE;
} // Calculate how many process identifiers were returned. cProcesses = cbNeeded / sizeof(DWORD); // Print the name of the modules for each process. for ( i = 0; i < cProcesses; i++ )
{
HANDLE hProcess = NULL; unsigned int k = 0; hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, aProcesses[i] );
if ( NULL == hProcess)
{
continue;
}
WCHAR wBuffer[1024];
::ZeroMemory( wBuffer, sizeof(wBuffer) );
int nCount = ::GetModuleFileNameEx ( hProcess, NULL, wBuffer, sizeof(wBuffer) - 2 );
CloseHandle( hProcess );
if ( nCount > 0 )
{
CString strPath = bstrExepath;
if ( strPath.CompareNoCase(wBuffer) == 0 )
{
*bExist = TRUE;
break;
} } }
return S_OK;
}STDMETHODIMP CMyScript::MyCreateProcess(BSTR bstrExePath, VARIANT_BOOL* bSuccess)
{
// TODO: Add your implementation code here
CString strPath = bstrExePath;
*bSuccess = VARIANT_FALSE; STARTUPINFO si;
PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if( !CreateProcess( strPath, // No module name (use command line)
NULL, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
return S_FALSE;
} // Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
*bSuccess = VARIANT_TRUE;
return S_OK;
}
重写OnStateChange,确认你的脚本引擎进入SCRIPTSTATE_CONNECTED状态。
建议去microsoft.public.scripting.hosting新闻组讨论这个问题。
/*[in]*/ DWORD dwReturnMask,
/*[out]*/ IUnknown **ppunkItem,
/*[out]*/ ITypeInfo **ppTypeInfo)
{
if(ppTypeInfo)
{
*ppTypeInfo = NULL; if(dwReturnMask & SCRIPTINFO_ITYPEINFO)
{
CComPtr< ITypeLib > sptLib;
::LoadTypeLib( L"MyScriptProject.tlb", &sptLib ); //装载自身的类型库
if( sptLib )
{
sptLib->GetTypeInfo( 0, ppTypeInfo );
}
} } if(ppunkItem)
{
*ppunkItem = NULL; if(dwReturnMask & SCRIPTINFO_IUNKNOWN)
{
if ( m_strObjName.Compare(pstrName ) == 0 )
{
ControlQueryInterface( IID_IUnknown, (LPVOID *)ppunkItem );
}
}
} return S_OK;
}
可能是类型库信息不对