logo WinWrap®

Client-Server Script Testing and Debugging via HTTP

WinWrap® Basic is an embedded language control available for .NET/COM 32/64 bit Windows applications. The WinWrap® Basic Component is compatible with VBA, Sax Basic, VB.NET and Visual Basic 6.0 style scripts.

Control and Debug a server or remote application's scripts. The Synchronized Property, Synchronize Method and Synchronizing Event (OnBasicSynchronizing Callback) work together to add remote control to WinWrap® Basic.

Client-Server Script Testing and Debugging via HTTP

  • Debug website server scripts
  • Use HTTP transport for synchronizing client and server
  • Set server script breakpoints from client debugger
  • Single step and run server script from client debugger
  • Evaluate server script expressions from client debugger

Debugging a Server Application Running WinWrap® Basic BasicNoUIObj Component

Client-Server Script Testing and Debugging via HTTP

Using scripting in a server application requires a script debugging capability. WinWrap® Basic's remote control capability allows scripts to debugged from the client.

An alternative server debug example is at http://www.winwrap.com/web2/solution/bp-AZW_Form. That AZW_Form example construct debug messages with accompaning annotated source script code to convey the specific script error information. In that example the debug error information is displayed in the client viewed webpage.

Server

This example server code is online at https://github.com/WinWrap/WinWrapExamples/tree/master/Example9 - AZW Debug.

This example server code is running at http://wwazwdebug2.azurewebsites.net/.

Set the synchronized mode.

Both the engine (server) and the debugger must have their Synchronized property set to True. The script execution in the engine is unchanged by the Synchronized property. However, the engine will fire a Synchronizing event whenever the engine needs to inform the debugger of a state change. The description of the state change is encoded in the Params parameter of the Synchonizing event. That data must be passed to the debugger's Synchronize method. This is what causes the debugger's state to track the engine's state.

basicNoUIObj.Initialize(); basicNoUIObj.AddScriptableObjectModel(typeof(ScriptingLanguage)); if (debug) { // prepare for debugging basicNoUIObj.Synchronized = true; Log("Debugging..."); }

Set the Handler's SetpInto mode.

using (var module = basicNoUIObj.ModuleInstance(ScriptPath(Script), false)) { if (module == null) throw basicNoUIObj.Error.Exception; if (debug) { // step into the script event handler module.StepInto = true; timelimit_ = DateTime.Now + new TimeSpan(0, 0, 30); // timeout in 30 seconds }

Synchronize with the remote Client Basic Control/Object.

foreach (string command in commands2) { // ignore heartbeat (only used to reset the timelimit) if (command != "*") { string[] parts = command.Split(new char[] { ' ' }, 2); int id = int.Parse(parts[0]); string param = Encoding.UTF8.GetString(Convert.FromBase64String(parts[1])); basicNoUIObj.Synchronize(param, id); } }

The Server's Synchronizing Event.

A Synchronizing Event occurs when the remote Client Basic Control/Object needs to synchronize.

void basicNoUIObj_Synchronizing(object sender, WinWrap.Basic.Classic.SynchronizingEventArgs e) { string response = e.Id + " " + Convert.ToBase64String(Encoding.UTF8.GetBytes(e.Param)) + "\r\n"; responses_.Append(response); }

Client

The client application uses a BasicIdeCtl control to manage the script's executional in the server.

Remote control allows the debugger to view engine code, set engine break points, single step and run the engine from the GUI.

This example client code is online at https://github.com/WinWrap/WinWrapExamples/tree/master/Example9 - Debugger.

You can run this code. Set remote server script breakpoints, watch variables, run until breakpoint, etc.

Remote Client

Set the synchronized mode.

basicIdeCtl1.Synchronized = true;

Synchronize with the remote Server Basic Control/Object.

foreach (string response in responses2) { string[] parts = response.Split(new char[] { ' ' }, 2); int id = int.Parse(parts[0]); string param = Encoding.UTF8.GetString(Convert.FromBase64String(parts[1])); log_.Append(" << " + param.Split(new string[] { "\r\n" }, 2, StringSplitOptions.None)[0]); basicIdeCtl1.Synchronize(param, id); }

The Client's Synchronizing Event.

A Synchronizing Event occurs when the remote Server Basic Control/Object needs to synchronize.

The client debugger will fire a Synchronizing event whenever it wants to control or query the engine. The Synchronizing event's Params data must be passed to the engine's Synchronize method.

private void basicIdeCtl1_Synchronizing(object sender, WinWrap.Basic.Classic.SynchronizingEventArgs e) { log_.Append(" >> " + e.Param); string command = e.Id + " " + Convert.ToBase64String(Encoding.UTF8.GetBytes(e.Param)) + "\r\n"; lock (lock_) commands_.Append(command); }

Transport

The particular client/server synchronizing message transport is chosen by the application developer. This example uses http as the transport mechanism.

The existing client/server connection can transport all the script debugging commands and execution status.

Getting the Synchronizing data to the other's Synchronize method requires some form of remote procedure call. If you already have a connection between your the debugger's host application and the engine's service, use that. Be sure to pass the Params and Id parameters unchanged between the Synchronizing event and the other's Synchronize method call.

Debugging server scripts by an authorized user requires some form of security mechanism to connect the debug client to the server application running the scripts. The security used is an architectural and implementation decision under the developer's control.

WinWrap® Basic uses a lazy form of synchronization. When the Synchronize method is called, the action is posted to the thread's windows message queue. The action will take place after the Synchronize method returns. So, don't expect the debugger and the engine to be in complete lockstep. This is a good thing, because the connection between the two might be slow.

Client Transport Code

The client debugger initiates and controls synchronizing message transport by issuing http requests to the server.

byte[] data = Encoding.UTF8.GetBytes("Commands:\r\n" + commands); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url_); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; request.Timeout = 5000; try { using (Stream newStream = request.GetRequestStream()) { newStream.Write(data, 0, data.Length); } // read the response asynchronously response_pending_ = true; ReadResponseAsync(request, commands); }

Server Transport Code

The server provides queued synchronizing data upon http requests from the client debugger.

public override string ReadAll() { HttpApplicationState appstate = HttpContext.Current.Application; appstate.Lock(); string text = (string)appstate[Name]; appstate[Name] = null; appstate.UnLock(); return text; }

Summary

WinWrap® Basic's remote control capability allows scripts to debugged from the client. Editing server scripts requires an "out-of-band" connection to the script store. The client application is not running any WinWrap® Basic code.

The WinWrap® Basic Scripting Control gives you the tools you need to debug powerful custom scripts on server applications.

Copyright Polar Engineering, Inc.