Starting in 1996, Alexa Internet has been donating their crawl data to the Internet Archive. Flowing in every day, these data are added to the Wayback Machine after an embargo period.
This article follows on from the Active Script Hosting discussions of Andrew Garbuzov.
Before you start on adding debugger support to your active script it's probably a good
idea to have active scripts up and running....
To experiment with the debugging interfaces, you will need an Active Script debugger
installed like the IE4 one available from Microsoft's
scripting site
A reference for the Active Script debugging interfaces was once provided in the online
reference but this now seems to have been moved off the Microsoft site. Even with this
documentation, implementing script debugging is far from trivial and the main aim of this
article is to give you a working sample to play with.
Warning - Because the Active Script Debugging interfaces do not seem to be fully
documented yet by Microsoft - in particular they have not provided any header files or
type libraries, the sample project attached to this article includes a hand built header
file, activscp_plus.h, which should be replaced with an offical MS version as soon as they
provide one.
In the "Running Documents" view of the IE4 debugger, click down the hierarchy
of the "MFC Scripting Documents" application and double-click on the
"VBScript - Scripter script block"
The IE4 debugger should now display some of the text of your script - in this you can
now place breakpoints to test the link between the debugger and the application. For
example, set a breakpoint in the AButton_OnClick handler and then click the AButton button
in the MFC application
Feel free to play with the debugger's "commands" window to view and alter
values in your script's code. For example, you can use the command window to print the
value of the edit control (use '? BroCon.LocationURL') or to set values or call methods
(try 'BroCon.Navigate "www.dilbert.com"')
Note: Microsoft have set up the script debugging so that Visual Interdev will
always be used in preference to the IE4 debugger. If you have Visual Interdev installed
then you can attach to the script using "Debug|Processes" and then choosing the
process "mfcaxsrvb.exe" in the dialog. The Interdev debugger gices you the
benefits of watchpoints and a watch window, a "Set Next Statement" command, and
generally better editing facilites.
Adding debugger support to an Active Script Host
To add debugging support to an Active Script Host, you need to perform the following
steps:
1. Before you initialise any of the IActiveScript classes, manually create an
IProcessDebugManager - this manager will control the debug process for you.
3. For each document (normally each script) you wish to run, create an
IDebugDocumentHelper to wrap the document. Define the short and long names of the document
and attach the document to your application
4. Support the IActiveScriptSiteDebug in your script host. This interface provides a
number of methods allowing a debugger to get the structure of the scripts in your
documents and to get the text of those documents.
BEGIN_INTERFACE_MAP(CMfcaxscrvbDlg, CDialog)
...
INTERFACE_PART(CMfcaxscrvbDlg,IID_IActiveScriptSiteDebug,ActiveScriptSiteDebug)
...
END_INTERFACE_MAP()
...
/////////////////////////////////////////////////////////////////////////////// IActiveScriptSiteDebug Implementation
STDMETHODIMP_(ULONG) CMfcaxscrvbDlg::XActiveScriptSiteDebug::AddRef()
{
METHOD_PROLOGUE_EX_(CMfcaxscrvbDlg, ActiveScriptSiteDebug)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CMfcaxscrvbDlg::XActiveScriptSiteDebug::Release()
{
METHOD_PROLOGUE_EX_(CMfcaxscrvbDlg, ActiveScriptSiteDebug)
return pThis->ExternalRelease();
}
STDMETHODIMP CMfcaxscrvbDlg::XActiveScriptSiteDebug::QueryInterface(REFIID iid, LPVOID* ppvObj)
{
METHOD_PROLOGUE_EX_(CMfcaxscrvbDlg, ActiveScriptSiteDebug)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
// Used by the language engine to delegate IDebugCodeContext::GetSourceContext.
STDMETHODIMP CMfcaxscrvbDlg::XActiveScriptSiteDebug::GetDocumentContextFromPosition(
DWORD dwSourceContext,// As provided to ParseScriptText // or AddScriptlet
ULONG uCharacterOffset,// character offset relative // to start of script block or scriptlet
ULONG uNumChars,// Number of characters in context // Returns the document context corresponding to this character-position range.
IDebugDocumentContext **ppsc)
{
METHOD_PROLOGUE_EX_(CMfcaxscrvbDlg, ActiveScriptSiteDebug)
ULONG ulStartPos = 0;
HRESULT hr;
if (pThis->m_pDebugDocHelper)
{
hr = pThis->m_pDebugDocHelper->GetScriptBlockInfo(dwSourceContext, NULL, &ulStartPos, NULL);
hr = pThis->m_pDebugDocHelper->CreateDebugDocumentContext(ulStartPos + uCharacterOffset, uNumChars, ppsc);
}
else
{
hr = E_NOTIMPL;
}
return hr;
}
// Returns the debug application object associated with this script site. Provides // a means for a smart host to define what application object each script belongs to. // Script engines should attempt to call this method to get their containing application // and resort to IProcessDebugManager::GetDefaultApplication if this fails.
STDMETHODIMP CMfcaxscrvbDlg::XActiveScriptSiteDebug::GetApplication(
IDebugApplication **ppda)
{
METHOD_PROLOGUE_EX_(CMfcaxscrvbDlg, ActiveScriptSiteDebug)
if (!ppda)
{
return E_INVALIDARG;
}
// bugbug - should addref to this ?if (pThis->m_pDebugApp)
{
ULONG ul = pThis->m_pDebugApp->AddRef();
}
*ppda = pThis->m_pDebugApp;
return S_OK;
}
// Gets the application node under which script documents should be added // can return NULL if script documents should be top-level.
STDMETHODIMP CMfcaxscrvbDlg::XActiveScriptSiteDebug::GetRootApplicationNode(
IDebugApplicationNode **ppdanRoot)
{
METHOD_PROLOGUE_EX_(CMfcaxscrvbDlg, ActiveScriptSiteDebug)
if (!ppdanRoot)
{
return E_INVALIDARG;
}
if (pThis->m_pDebugDocHelper)
{
return pThis->m_pDebugDocHelper->GetDebugApplicationNode(ppdanRoot);
}
return E_NOTIMPL;
}
// Allows a smart host to control the handling of runtime errors
STDMETHODIMP CMfcaxscrvbDlg::XActiveScriptSiteDebug::OnScriptErrorDebug(
// the runtime error that occurred
IActiveScriptErrorDebug *pErrorDebug,
// whether to pass the error to the debugger to do JIT debugging
BOOL*pfEnterDebugger,
// whether to call IActiveScriptSite::OnScriptError() when the user // decides to continue without debugging
BOOL *pfCallOnScriptErrorWhenContinuing)
{
METHOD_PROLOGUE_EX_(CMfcaxscrvbDlg, ActiveScriptSiteDebug)
if (pfEnterDebugger)
{
*pfEnterDebugger = TRUE;
}
if (pfCallOnScriptErrorWhenContinuing)
{
*pfCallOnScriptErrorWhenContinuing = TRUE;
}
return S_OK;
}
5. Before you parse the script text using IActiveScriptParse, add the script text to
the IDebugDocumentHelper and define the script as a text.
7. [optional] The sample code included with this article also provides a simple
IDebugDocumentHost implementation. This interface does not get used to its full extent by
the IE4 debugger, but other Active Debuggers may use it more fully. Among the capabilities
of this interface are customisation of script syntax coloring and provision of file path
names and methods to react to the debugger changing document text.
Add www.codeguru.com to your favorites Add www.codeguru.com to your browser search box IE 7 | Firefox 2.0 | Firefox 1.5.xReceive news via our XML/RSS feed
RATE THIS ARTICLE:
Excellent Very Good Average Below Average Poor
(You must be signed in to rank an article. Not a member? Click here to register)