Board index » delphi » Using Microsoft's Script Control 1.0 in Delphi 3

Using Microsoft's Script Control 1.0 in Delphi 3

Has anyone tried using Microsoft's Script Control (Msscript.ocx) in
Delphi 3 with any success?

I've found the Eval method to work fine, however, I'm experiencing
problems in two other areas:

    1. The Run method uses a PSafeArray (defined in the ActiveX unit)
for the Parameters.  When I set up an empty PSafeArray (I'm not using
any Parameters) I receive an Access Violation.
    2. When attempting to used the AddObject method, it requires an
IDispatch parameter type.  How do you typecast a Variant into an
IDispatch? Or return the IDispatch of the Variant object, created with
CreateOleObject?

-- EJS

 

Re:Using Microsoft's Script Control 1.0 in Delphi 3


Hi Edward,

Quote
>    1. The Run method uses a PSafeArray (defined in the ActiveX unit)
>for the Parameters.  When I set up an empty PSafeArray (I'm not using
>any Parameters) I receive an Access Violation.

This calls a function or sub with parameters:

procedure TForm1.Button2Click(Sender: TObject);
var  V: Variant;
begin
  V := VarArrayOf(['test1', 'test2', 'test2']);
  ScriptControl1.Run('Test', PSafeArray(TVarData(V).VArray));
end;

This calls a function or sub without params:
procedure TForm1.Button2Click(Sender: TObject);
var
    psa: PSafeArray; (* Used to allocate a safe array *)
    sab: TSafeArrayBound; (* Array bound descriptor *)
begin
    sab.lLbound := 0;
    sab.cElements := 0;
    psa := SafeArrayCreate(VT_VARIANT, 1, sab);
    scriptControl1.run ('Test', psa);
    SafeArrayDestroy (psa);
end;

One other way to archive the same if the name is known at design time is:
procedure TForm1.Button2Click(Sender: TObject);
var  V: Variant;
begin
  v := scriptControl1.CodeObject;
  v.Test ('test1, 'test2', 'test3');
end;

Quote
>    2. When attempting to used the AddObject method, it requires an
>IDispatch parameter type.  How do you typecast a Variant into an
>IDispatch? Or return the IDispatch of the Variant object, created with
>CreateOleObject?

Simply specify the object like:
  scriptControl1.AddObject ('KV1', TTestObject.create (self), true);

TTestObject must have an IDispatch Interface. By adding this object, the
script control is getting full control over the object and will free the
object.

Hope this helps,

Martin

Re:Using Microsoft's Script Control 1.0 in Delphi 3


If you do not use any parameters you can simply typecast to an olevariant,
like:

//Partial code
var
  Script:iScriptControl;

begin
  Script:=CreateComObject(Class_ScriptControl) As iScriptControl;
  //Add some code from a memocontrol
  Script.AddObject(Widestring(Memo1.Lines.text);
  //Execute a subroutine or function by its name
  Olevariant(Script).Run(procedureName);
 end;

Quote
Edward J. Stembler wrote in message <3556743A.4B30D...@mindspring.com>...
>Has anyone tried using Microsoft's Script Control (Msscript.ocx) in
>Delphi 3 with any success?

>I've found the Eval method to work fine, however, I'm experiencing
>problems in two other areas:

>    1. The Run method uses a PSafeArray (defined in the ActiveX unit)
>for the Parameters.  When I set up an empty PSafeArray (I'm not using
>any Parameters) I receive an Access Violation.
>    2. When attempting to used the AddObject method, it requires an
>IDispatch parameter type.  How do you typecast a Variant into an
>IDispatch? Or return the IDispatch of the Variant object, created with
>CreateOleObject?

>-- EJS

Re:Using Microsoft's Script Control 1.0 in Delphi 3


I've tried this wednesday. I had similar problems.

I found the solution is to bypass the early binding mechanism's.

I've been able to run a macro using the following code :

procedure TForm1.Button1Click(Sender: TObject);
var App : IDispatch ;
    A : Variant ;
    B : Olevariant ;
    Module : Variant ;
    Str : String ;
begin
  App := TApp.Create as IApp ;  // using an IDispatch from my own
application.
  ScriptControl1.AddObject('Application',App,True);
  A := 'Module1' ;  // this is a variant !!!
  B := App ;
  Module := ScriptControl1.Modules.Add('Module1',B);
// the module is a variant, wich means latetime biding, but it works.
  Str := 'Sub MijnSub ' + CRLF + 'MsgBox "Hello Edwin, this is the
ScriptControl" '
          + CRLF + 'Application.Message ' + CRLF + 'End Sub' ;
  Module.AddCode(Str);
  Module.Run('MijnSub');  // uses late binding thruogh Variants.
                see .. no extra variable required !
  //Module.CodeObject.MijnSub ; //
end;

Let me explain, The Module variable is a variant, so it can do what
Delphi can't, that is it just ommits
the SafeArray. (It took me hours to figure this out ! ) In VB everything
with OLE will run using variants, even if it looks otherwise. An Object
variable in VB is really just a variant with an interface for the object
it refers to. Basically VB programmers have no idea off what they are
really doing !!

The App variable here is just an OleAutomation object that I have added
to my application thruogh
New...ActiveX...OleAutomation object.  Its an IDispath right away.

Recently I saw the question on how to get an variant from an IDispatch
in this newsgruop. There is a function for it
but I forgot it. You migth want to post a question with this sepcific
question.

Never mind though. Here's the solution that will solve most of your
problems wtih the control:

If you want access similar to VB as the documentation descibes you will
want to work completely using variant.
(Be warned it slower.  My application seems rather slow anyway, not
because of the control I think.)

Its simple : cast your control to a variant :

procedure TForm1.Button2Click(Sender: TObject);
var App : Variant ;  // variant. this time
    A : Variant ;
    B : Olevariant ;
    Module : Variant ;
    Str : String ;
    ScriptControl : Variant ;
begin
  ScriptControl := ScriptControl1.ControlInterface ;   !!!!!!!!!!

(*The previous line puts the interface for the scriptcontrol in a
variant. Now everything will work as in VB.
(Hey I'm trowing a IDispatch right into a variant here, I think. Perhaps
its a bit simpler than I thought. Getting the IDispatch from the variant
will be harder.)  *)

  App := TApp.Create as IApp ; // once again putting an interface into a
variant.
  ScriptControl.AddObject('Application',App,True);
  A := 'Module1' ;
  B := App ;
  Module := ScriptControl.Modules.Add('Module1',B);
  Str := 'Sub MijnSub ' + CRLF + 'MsgBox "Hello Edwin, this is the
ScriptControl" '
          + CRLF + 'Application.Message ' + CRLF + 'End Sub' ;
  Module.AddCode(Str);
  Module.Run('MijnSub');
  //Module.CodeObject.MijnSub ;
end;

I've pasted the code straigth in here, the same as I wrote it yesterday
evening, when I was facing the same problems.
By the way, as you can see, my App interface automation object supports
a Message function.
This function just says "Hello", but I'm calling it from VBScript here.
Its named Application because that's what i called in the
AddObject function. This is the way to allow a client to program your
Delphi application. Supply the application with an
number of Automation objects, and add the control. ( And write a small
editor.)

I havent been able to figure out how to use SafeArrays myself. There are
some help function in the ActiveX.pas file.
I've tried it, but I get an 'incorrect parameter' message. (In dutch so
the message is from the Control, not from Delphi.)
I can't find any help files on SafeArrays. Its like the Borland guys are
trying to pretend it they don't exist.
The help files just mention to use variant arrays, but that won't work.

If you put the control ControlInterface into a variant everything should
work. I'll be working on this myself
in the next days.

Edwin Teisman e.teis...@wxs.nl (home) or teis...@defacto.nl (work)

Good luck !!

( one last thing, I've read its possible to call createObject in
VBScript. This means applications like Word can also be accessed from
the control. Great ! )

Other Threads