In the past, when I was working on a workflow project, one of the items was that when the user made a process definition, he could write a script to control the jump of the activity. These scripts are defined and stored in the database, when a stream starts, the workflow engine controls the execution sequence of the activity. String-type two activities are relatively simple, but some activities reach the next activity with conditional judgment or multiple branches, it's easy. You only need to add a field to the database table to implement it. To be more complex, you need to implement it through scripts. I didn't have enough experience at the time, but I didn't find a quick solution for a few days. I was not sure about writing a Custom Script Engine myself, and I didn't have enough time. I 'd like to find it on the Internet. It took some time, I found a solution that I think is better, and wrote it to share it with you.
The following two sections describe the implementation and application.
1. Use msscriptcontrol
Download Windows Script control from Microsoft website. It is an ActiveX (r) control, so I used InterOP in. net. After the download and installation are complete, create a C # windows application project, select the reference node in solution Resource Manager, right-click and choose add reference from the shortcut menu, and the Add reference dialog box is displayed, click Browse to find the directory for installing Windows Script control and select msscript. ocx file. A msscriptcontrol component is added to the reference node. The following are all objects after InterOP.
Scriptcontrol provides simple interfaces for the host script engine that supports ActiveX (TM) scripts. Next, we will explain the attributes and methods of the scriptcontrol converted to the scriptcontrolclass class.
Attribute
Allowui attribute: applies to the user interface elements displayed by scriptcontrol itself or scirpt engine, and can be read and written.
Codeobject attribute: return object, which is used to call public members of a specified module. Read-only.
Error attribute: return the error object, which contains detailed information about the last error. Read-only.
Language attribute: sets or returns the name of the script language in use. Read/write.
Modules attribute: a set of return modules for the scriptcontrol object. Read-only.
Procedures attribute: return the process set defined in the specified module. Read-only.
Sitehwnd property: set or return the hwnd of the window. By executing script code, this window is used to display the dialog box and other user interface elements. Read/write.
State attribute: sets or returns the mode of the scriptcontrol object. Read/write.
Timeout attribute: set or return time (MS). After this time, you can choose to abort the execution of the script code or allow the code to continue. Read/write.
Usesafesubset attribute: sets or returns a Boolean value to indicate whether the host application has confidentiality requirements. If the host application requires security control, usesafesubset is true; otherwise, it is false. Read/write.
Method
Addcode: add the specified code to the module. You can call the addcode method multiple times.
Addobject method: Make the Host Object Model Available to the script engine.
Eval method: calculates the expression and returns the result.
Executestatement method: run the specified statement.
Reset method: discard all script code and objects that have been added to scriptcontrol.
Run method: run the specified process.
Event
Error Event: This event occurs when a running error occurs.
Timeout event: This event occurs when the time specified by the timeout attribute is exceeded and the end is selected in the result dialog box.
Additional points
If the allowui attribute is set to false, statements such as the displayed dialog box do not work, such as msgbox statements in VBScript and alert in Javascript. If the executed scripts exceed the milliseconds set in timeout, the dialog box that exceeds the time reminder will not pop up, and vice versa. Resetting the language attribute will clear the code loaded by addcode. For the timeout attribute, when the time-out occurs, scriptcontrol checks the allowui attribute of the object, determine whether to allow display of user interface elements.
For more information, see the msdn documentation.
To make the control easier to use, I wrapped it in a scriptengine class. The following is the complete code:
Using system; </P> <p> using msscriptcontrol; </P> <p> using system. text; </P> <p> namespace ZZ </P> <p >{</P> <p> // <summary> </P> <p> /// script Type </P> <p> // </Summary> </P> <p> Public Enum scriptlanguage </P> <p >{</P> <p >/// <summary> </P> <p> // JScript Language </P> <p> /// </Summary> </P> <p>> JScript, </P> <p> // <summary> </P> <p> // VBScript language </P> <p> // </Summary> </P> <p> VBScript, </P> <p> // <summary> </P> <p> // Objective C </P> <p> // </Summary> </P> <p> JavaScript </P> <p >}</P> <p> /// <summary> </P> <p> // script running error proxy </P> <p> /// </Summary> </P> <p>> Public Delegate void runerrorhandler (); </P> <p> // <summary> </P> <p> // script operation timeout proxy </P> <p> /// </Summary> </P> <p> Public Delegate void runtimeouthandler (); </P> <p> // <summary> </P> <p> // scriptengine class </P> <p> // </Summary> </P> <p> public class scriptengine </P> <p >{</P> <p> PRI Vate scriptcontrol MSC; </P> <p> // defines the script running error event </P> <p> public event runerrorhandler runerror; </P> <p> // defines the script running timeout event </P> <p> public event runtimeouthandler runtimeout; </P> <p> // <summary> </P> <p> // constructor </P> <p> /// </Summary> </P> <p> Public scriptengine (): This (scriptlanguage. VBScript) </P> <p >{</P> <p >}</P> <p> // <summary> </P> <p> // construct function </P> <p> // </Summary> </P> <p> // <Param name = "language"> Script Type </param> </P> <p> Public scriptengine (scriptlanguage language) </P> <p >{</P> <p> This. MSC = new scriptcontrolclass (); </P> <p> This. MSC. usesafesubset = true; </P> <p> This. MSC. language = language. tostring (); </P> <p> (dscriptcontrolsource_event) This. MSC ). error + = new dscriptcontrolsource_erroreventhandler (scriptengine_error); </P> <p> (dscriptcontrolsource_event) This. MSC ). timeout + = new dscriptcontrolsource_timeout Eventhandler (scriptengine_timeout ); </P> <p >}</P> <p> // <summary> </P> <p> // run the eval method </P> <p>> /// </Summary> </P> <p> // <Param name = "expression"> Expression </param> </P> <p> // /<Param name = "codebody"> function body </param> </P> <p> // <returns> returned object </returns> </P> <p> Public object eval (string expression, string codebody) </P> <p >{</P> <p> MSC. addcode (codebody); </P> <p> return MSC. eval (expression); </P> <p >}</P> <p> // <s Ummary> </P> <p> // run the eval method </P> <p> // </Summary> </P> <p> // <param name = "language"> script language </param> </P> <p> // <Param name = "expression"> Expression </param> </P> <p> // <Param name = "codebody"> function body </param> </P> <p> // <returns> returned object </returns> </P> <p> Public object eval (scriptlanguage language, string expression, string codebody) </P> <p >{</P> <p> If (this. language! = Language) </P> <p> This. language = language; </P> <p> return eval (expression, codebody ); </P> <p >}</P> <p> // <summary> </P> <p> // run the run method </P> <p>> /// </Summary> </P> <p> // <Param name = "mainfunctionname"> name of the entry function </param> </P> <p> /// <Param name = "Parameters"> parameter </param> </P> <p> // <Param name = "codebody"> function body </param> </P> <p> // <returns> return value object </returns> </P> <p> Public object run (string mainfunctionname, objec T [] parameters, string codebody) </P> <p >{</P> <p> This. MSC. addcode (codebody); </P> <p> return MSC. run (mainfunctionname, ref parameters ); </P> <p >}</P> <p> // <summary> </P> <p> // run the run method </P> <p>> /// </Summary> </P> <p> // <Param name = "language"> script language </param> </P> <p>/ // <Param name = "mainfunctionname"> name of the entry function </param> </P> <p> // <Param name = "Parameters"> parameter </param> </P> <p> // <Param name = "codebody"> function body </param> </P> <p> // <returns> return value object </returns> </P> <p> Public object run (scriptlanguage language, string mainfunctionname, object [] parameters, string codebody) </P> <p >{</P> <p> If (this. language! = Language) </P> <p> This. language = language; </P> <p> return run (mainfunctionname, parameters, codebody ); </P> <p >}</P> <p> // <summary> </P> <p> // discard all script code added to scriptcontrol. and object </P> <p> // </Summary> </P> <p> Public void reset () </P> <p >{</P> <p> This. MSC. reset (); </P> <p >}</P> <p> // <summary> </P> <p> // obtain or set the script language <br/> /// </Summary> </P> <p> Public scriptlanguage language </P> <p >{</P> <p> get {return (Scriptlanguage) enum. parse (typeof (scriptlanguage), this. MSC. language, false) ;}</P> <p> set {This. MSC. language = value. tostring ();} </P> <p >}</P> <p> // <summary> </P> <p> // obtain or set the script execution time, unit: millisecond </P> <p> // </Summary> </P> <p> Public int timeout </P> <p >{</P> <p> get {return this. MSC. timeout ;}</P> <p> set {This. MSC. timeout = value ;} </P> <p >}</P> <p> // <summary> </P> <p> // set whether to display user interface elements </P>> <p> // </Summary> </P> <p> Public bool allowui </P> <p >{</P> <p> get {return this. MSC. allowui ;}</P> <p> set {This. MSC. allowui = value ;} </P> <p >}</P> <p> // <summary> </P> <p> // whether the host application has confidentiality requirements </P>/ p> <p> // </Summary> </P> <p> Public bool usesafesubset </P> <p >{</P> <p> get {return this. MSC. usesafesubset ;}</P> <p> set {This. MSC. usesafesubset = true ;} </P> <p >}</P> <p> // <summary> </P> <p> // triggered by a runerror event </P> <p>> /// </Summary> </P> <p> priva Te void onerror () </P> <p >{</P> <p> If (runerror! = NULL) </P> <p> runerror (); </P> <p >}</P> <p> // <summary> </P> <p> // ontimeout event excitation </P> <p> >/// </Summary> </P> <p> private void ontimeout () </P> <p >{</P> <p> If (runtimeout! = NULL) </P> <p> runtimeout (); </P> <p >}</P> <p> private void scriptengine_error () </P> <p >{</P> <p> onerror (); </P> <p >}</P> <p> private void scriptengine_timeout () </P> <p >{</P> <p> ontimeout (); </P> <p >}</P> <p>}
The above packaging defines a scriptlanguage enumeration, which makes it easier to operate. In addition, the script engine includes error events and timeout events, which can be registered based on actual usage.
Ii. Script Engine demonstration
I have created a form program to test whether to enable the allowui attribute, set the time-out period, and select a method to call the script engine. The code of the test program is long and the main parts are listed below:
Using system; </P> <p> using system. drawing; </P> <p> using system. collections; </P> <p> using system. componentmodel; </P> <p> using system. windows. forms; </P> <p> using system. data; </P> <p> namespace ZZ </P> <p >{</P> <p> public class form1: system. windows. forms. form </P> <p >{</P> <p> private scriptengine; </P> <p> private system. windows. forms. checkbox checkboxallowui; </P> <p> private system. windows. forms. tex Tbox textboxresult; </P> <p> private system. windows. forms. numericupdown numericupdowntimeout; </P> <p> private system. windows. forms. textbox textboxcodebody; </P> <p> private system. windows. forms. button buttonrun; </P> <p> private system. windows. forms. button buttoncancel; </P> <p> private system. windows. forms. comboBox comboboxscript; </P> <p> private system. windows. forms. textbox textboxparams; </P> <p> private s Ystem. windows. forms. radiobutton radiobuttoneval; </P> <p> private system. windows. forms. radiobutton radiobuttonrun; </P> <p> private system. windows. forms. textbox textboxmethodname; </P> <p> private system. componentmodel. container components = NULL; </P> <p> Public form1 () </P> <p >{</P> <p> initializecomponent (); </P> <p> This. comboboxscript. selectedindex = 0; </P> <p> This. scriptengine = new scriptengine (); </P> <P> This. scriptengine. usesafesubset = true; </P> <p> This. scriptengine. runerror + = new runerrorhandler (scriptengine_runerror); </P> <p> This. scriptengine. runtimeout + = new runtimeouthandler (scriptengine_runtimeout); </P> <p >}</P> <p> protected override void dispose (bool disposing) </P> <p >{</P> <p> If (disposing) </P> <p> If (components! = NULL) </P> <p> components. dispose (); </P> <p> base. dispose (disposing ); </P> <p >}</P> <p> # code generated by region windows Form Designer </P> <p> private void initializecomponent () </P> <p >{</P> <p> // omitted </P> <p >}</P> <p> # endregion </P> <p> [stathread] </P> <p> static void main () </P> <p >{</P> <p> application. run (New form1 ()); </P> <p >}</P> <p> // run the script </P> <p> private void buttonrun_click (Object sender, system. eventargs e) </P> <p >{</P> <P> This. scriptengine. reset (); </P> <p> This. scriptengine. language = (scriptlanguage) enum. parse (typeof </P> <p> (scriptlanguage), this. comboboxscript. selecteditem. tostring (); </P> <p> This. scriptengine. timeout = (INT) This. numericupdowntimeout. value; </P> <p> This. scriptengine. allowui = This. checkboxallowui. checked; </P> <p> If (this. radiobuttoneval. checked) // run the eval method </P> <p >{</P> <p> This. textboxresult. TEXT = This. scriptengine. eval </P> <p> (this. textboxmethodname. text + "(" + this. textboxparams. text + ")", this. textboxcodebody. text ). tostring </P> <p> (); </P> <p >}</P> <p> else // run the run method </P> <p >{</P> <p> string [] Parameters = (string []) this. textboxparams. text. split (','); </P> <p> object [] paramarray = new object [parameters. length]; </P> <p> for (INT I = 0; I <parameters. length; I ++) </P> <p> paramarray [I] = int32.parse (paramete RS [I]); </P> <p> This. textboxresult. TEXT = This. scriptengine. run </P> <p> (this. textboxmethodname. text, paramarray, this. textboxcodebody. text ). tostring (); </P> <p >}</P> <p> // exit the Program </P> <p> private void buttoncancel_click (Object sender, system. eventargs e) </P> <p >{</P> <p> This. close (); </P> <p >}</P> <p> // error function </P> <p> private void scriptengine_runerror () </P> <p >{</P> <p> MessageBox. show ("runerror execution Script Error! "); </P> <p >}</P> <p> private void scriptengine_runtimeout () </P> <p >{</P> <p> MessageBox. show ("runtimeout script execution times out, causing an error! "); </P> <p >}</P> <p>}
The following is the test program running interface:
A JavaScript function is written in the text box. Input 12 and output 12000012.
If the timeout time is adjusted to 1 ms, executing the script will jump out of the following timeout reminder box and trigger the event.
Summary: The Javascript script is demonstrated above. If you are interested, you can write some vbsript functions for testing. The script language only lists
Three. After reading help, he also supports other scripts. If needed, you can add them. In addition, because it calls COM, some return values are obejct.
Type, which must be converted. In csdn Technical Forum C #, some people often ask questions in this regard,
Hope you can get some help through this article, and I am very happy to be able to communicate with friends who are engaged in. net.
Address: http://www.kingacc.com/info/2008/12/22/20081222-84.html