Getting started

 

SETUP. First of all, please check that you find side by side wizapi32.dll and scriptez.dll in the same folder. Then, you need to register the COM scriptez.dll  file under Windows like this: regsvr32.exe scriptez.dll ( from within a command line prompt - aka DOS console black window ) which will display the following message box.

 

image003

 

Sometimes, to resolve the reason why registration fails under Windows 8.x and Windows 10, DOS console should be started as an Administrator user before running regsvr32.exe scriptez.dll

 

Otherwise, in the case where registering fails because of administrative restrictions (due to a lockdown policy) on a computer, you can use and configure manifest XML files such like here. Moreover, thanks to the Registration-free technology which was introduced into Windows XP SP2 up to recent Windows flavours, you can actually embed a manifest file into a target .exe file with Manifest Tool (mt.exe) in order to facilitate side by side deployment of applications.

 

Indeed, you can additionally use another tool application called Manifest File Maker (aka ManifestFileMaker.exe which is included with the Setup package) to find and/or to generate interactively manifest files for any application and any COM DLL file:

 

 

 

ScriptEZ.API component can be instantiated with two ways. The first one creates the main object which contains IAPI interface where properties and methods can directly be invoked; the second one creates the main object and installs a callback interface named _IAPIEvents where client code must or can implement some of callback functions, so the component will be asynchronously able to forward or to exchange status, messages and behaviour at runtime.

 

 

(1) Instantiating ScriptEZ.API object with VBScript:

 

 ’ Example 1: instantiate component object

 Set ScriptEZ = WScript.CreateObject("ScriptEZ.API")

 Or

 Set ScriptEZ = CreateObject("ScriptEZ.API")

 

 ’ Example 2: instantiate component object with callback interface

 Set ScriptEZ = WScript.CreateObject("ScriptEZ.API","ScriptEZ_")

 ScriptEZ.AppRegister ' Activate Remoting Control Interface

 

 

 Function ScriptEZ_AppEventHelp()

   ScriptEZ_AppEventHelp = CStr(“Self documentation here”)

 End Function

 

(2) Instantiating ScriptEZ.API object with Visual Basic 6.0:

 

Execute “Project/References” command, browse and select ‘ScriptEZ 1.0 Type Library’ as following:

 

References

 

 

‘ Example 1

Option Explicit

Public ScriptEZ As API

 

' Form load event

Public Sub Form_Load()

    Set ScriptEZ = New API

    ScriptEZ.AppRegister ' Activate Remoting Control Interface

End Sub

 

 

‘ Example 2

Option Explicit

Public WithEvents ScriptEZ As API

 

' Form load event

Public Sub Form_Load()

    Set ScriptEZ = New API

    ScriptEZ.AppRegister ' Activate Remoting Control Interface

End Sub

Private Function ScriptEZ_AppEventHelp() As String

    ScriptEZ_AppEventHelp = "Hello World !" + vbLf + "...I am a VB6 Application."

End Function

 

(3) Instantiating ScriptEZ.API object with PHP 5.3.x:

 

// Example 1

// create component object

$ScriptEZ = new COM("ScriptEZ.API");

 

// Example 2

class ScriptEZ_EventHandlers

{

    // Remoting Control Interface

    function AppEventHelp()

    {

       $AppEventHelp = "  **** Supported AppEvents ****" . "\n" .

                       "AppEventID = 3" . "\t" . "to exit" . "\n";

       return  $AppEventHelp;

    }

 

}

// create component object and event sink class

$ScriptEZ = new COM("ScriptEZ.API");

$sink     = new ScriptEZ_EventHandlers();

$ScriptEZ->AppRegister(); // Activate Remoting Control Interface

 

// install event sink class

com_event_sink($ScriptEZ, $sink, "_IAPIEvents");

 

 

(4) Instantiating ScriptEZ.API object with C/C++:

 

 HRESULT hr;

 // Init MTA (Multi Thread Apartment)

 hr = ::CoInitializeEx(NULL,COINIT_MULTITHREADED);

 

 CIAPIEventsSink *pIAPIEventsSink;

 DWORD dwAdvise;

     

 // instantiate a ScriptEZ.API object

 hr = CoCreateInstance(CLSID_API,NULL,CLSCTX_INPROC,IID_IAPI,(void**)&pIAPI);

 if(hr == S_OK)

 {

  pIAPI->SetConsoleTitle(L"ScriptEZ.API Demo App in C++: TCP/IP & ThreadPool Usage");

 

  /// Installing connection point (callback in COM/DCOM way)

  IConnectionPointContainer *pcpc = NULL;

  IConnectionPoint *pcp = NULL;

  hr = pIAPI->QueryInterface(IID_IConnectionPointContainer,(void**)&pcpc);

  if(SUCCEEDED(hr))

  {

   hr = pcpc->FindConnectionPoint(DIID__IAPIEvents,&pcp);

   if(SUCCEEDED(hr))

   {

    pIAPIEventsSink = CreateIDispatchEventObjectEx<CIAPIEventsSink>(DIID__IAPIEvents);

    hr = pcp->Advise((IUnknown*)pIAPIEventsSink,&dwAdvise);

   }

  }

 }

 

 

(5) Instantiating ScriptEZ.API object with .NET Framework can be done through COM Interop.

  (please, refer to provided samples in VB.NET)

 

 

 

(6) Instantiating ScriptEZ.API object with C#:

 

Here is an excerpt of code in C# from a simple Console Application (provided among other samples) which is using

ScriptEZ.API component’s methods and properties. It is illustrating the use of the remote control interface, the use

of a thread pool, the use of auto-restarting app mechanism (crash resilience) and so on, from ScriptEZ.API.

 

using System;

using System.Threading;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

using SCRIPTEZLib;

namespace ConsoleApp

{

    class Program

    {

        public static SCRIPTEZLib.API scriptEZ;

        public static COMEventSink comSink;

        public static System.Runtime.InteropServices.ComTypes.IConnectionPoint icp;

        public static int cookie;

        public static bool exitApp = false;

        public static int[] task_exec_counter = new int[7];

 

        // Multi-threaded context....

        [MTAThread]

        static void Main(string[] args)

        {

            Thread oThread = new Thread(new ThreadStart(ThreadStart));

            oThread.SetApartmentState(ApartmentState.MTA);

            oThread.Start();

 

            while (!exitApp)

            {

               /// Yielding control

               Thread.Sleep(10);

            }

 

            if (comSink.watchDogProcessID > 0)

            {

               scriptEZ.Terminate(comSink.watchDogProcessID);

            }

 

            // 4. Uninstall COM Event Sink

            icp.Unadvise(cookie);

 

            oThread.Abort();

        }

        /// <summary>

        /// .NET thread procedure

        /// </summary>

        public static void ThreadStart()

        {

           /// Instantiating the COMponent object

           scriptEZ = new SCRIPTEZLib.API();

           if (scriptEZ != null)

           {

               /// Mapping affinity to CPU Core1

               scriptEZ.SetCPUCoreAffinity("0");

 

               /// Just an echo

               scriptEZ.Echo("Who said...that COM became \"has been\" ?!");

 

               /// Setup Remote Control Interface

               scriptEZ.AppRegister("");

 

               /// Instantiating and setting up the COM Event Sink (callback)

               comSink = new COMEventSink();

               comSink.scriptEZ = scriptEZ;

 

               System.Runtime.InteropServices.ComTypes.IConnectionPointContainer icpc;

               // 1. Search for Connection point container

               icpc = (System.Runtime.InteropServices.ComTypes.IConnectionPointContainer)scriptEZ;

              

               Guid IID_IAPIEvents = typeof(_IAPIEvents).GUID;

               // 2. Search for a Connection point

               icpc.FindConnectionPoint(ref IID_IAPIEvents, out icp);

               // 3. Handshaking COM Event Sink with the Connection point

               icp.Advise(comSink, out cookie);

 

               /// Create a pool of 4 threads for executing 2 jobs

               int threadPool = scriptEZ.get_CreateTaskQueueObject(4);

               for (int i = 1; i <= 7; i++)

               {

                   scriptEZ.get_AddTask(threadPool,i);// Task#i

               }

           }

        }

    }

   

    /// <summary>

    /// Implementing _IAPIEvents callback interface (early binding)

    /// Note that all functions must be declared and defined, even though NOT USED.

    /// </summary>

    class COMEventSink : _IAPIEvents

    {

        public int watchDogProcessID = 0;

        public SCRIPTEZLib.API scriptEZ;

 

        //////// Application ///////////

        public string AppEventHelp()

        {

            string task_exec = "Tasks execution counter:\n";

            for (int i = 0; i < 7; i++)

            {

                task_exec = task_exec + " .TaskID " + (i+1).ToString()  +

                            " executed " + Program.task_exec_counter[i].ToString() + " times\n";

            }

 

            return "Welcome in a COM World !\n<Enter>\n" +

                   " -9 to exit gracefully the program\n" +

                   "  8 to enable auto-restart feature\n" +

                   (watchDogProcessID > 0 ? "\nWatchdog Process ID: " + watchDogProcessID.ToString():"") + "\n" +

                   task_exec;

        }

 

        public void onAppEvent(int EventID)

        {

            switch (EventID)

            {

                case -9: Program.exitApp = true;

                         break;

                case 8 : if(watchDogProcessID == 0) watchDogProcessID = scriptEZ.get_AppAutoRestart("");

                         break;

                default: break;

            }

        }

 

        public int onTimer(int IDTimerEvent)

        {

            return 0;

        }

 

        //////// Thread pool ///////////

        public int onRun(int task_local_storage)

        {

            scriptEZ.Sleep(300);

            Program.task_exec_counter[task_local_storage - 1]++;

            System.Console.WriteLine(" TaskID:" + task_local_storage +

                                     " Pooled Thread ID: " + scriptEZ.GetCurrentPooledThreadId +

                                     (task_local_storage == 2 ? " (Who said that COM has been ?!)":""));

            if (task_local_storage == 2)

            {

                int currentProcessID = scriptEZ.GetCurrentProcessId;

                int ram = (scriptEZ.get_ProbeMemoryStatus(currentProcessID));

                scriptEZ.SetConsoleTitle("Own used memory: " + ram.ToString() +

                                         " Bytes | Thread number: " + scriptEZ.get_ProbeMemoryStatus(-4) +

                                         " | Open Handle number: " + scriptEZ.get_ProbeMemoryStatus(-7));

            }

            return 1;

        }

        public void onAbort(int appID)

        {

        }

 

        //////// TCP/IP ///////////

        public int onConnectionRequest(int hSocketClientObjectProxy)

        {

            return 0;

        }

 

        public int onConnectionState(int hOwnerSocket, string state_desc, int error_number)

        {

            System.Console.Write(state_desc + ":" + error_number.ToString() );

            return 0;

        }

 

        public int onData(int hOwnerSocket, int raw_data, int data_size)

        {

            return 0;

        }

 

        //////// Named Pipe ///////////

        public int onConnectionRequestNamedPipe(int hNamedPipeClientObjectProxy)

        {

            return 0;

        }

 

        public int onConnectionStateNamedPipe(int hOwnerNamedPipe, string state_desc, int error_number)

        {

            System.Console.Write(state_desc + ":" + error_number.ToString());

            return 0;

        }

 

        public int onDataNamedPipe(int hOwnerNamedPipe, int raw_data, int data_size)

        {

            return 0;

        }

 

        //////// ServerDoc Application ///////////

        public int onServerDocData(int DataRows, int RowCount, int DataSize)

        {

            return 0;

        }

 

        public int onServerDocStatus(int Status)

        {

            return 0;

        }

    }

}