Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.177 Beiträge
 
Delphi 12 Athens
 
#2

AW: Windows Scripting Host (WSH)

  Alt 5. Nov 2023, 17:16
Ach ja, alles natürlich auch für Win64.
Viele Beispiele im Internet funktionieren hier nicht, da zwar die Interfaces "gleich" sind, aber Viele eine andere GUID besitzen.

Auch muß beachtet werden, dass installierte Fremd-Sprachen in der jeweiligen Bittigkeit (oder Beides) installiert sein müssen. (zumindestens bei den In-Process-Servern)



So, und hier noch ein winziger nativer Ansatz:
https://stackoverflow.com/questions/...-from-within-c
Delphi-Quellcode:
uses
  System.SysUtils, System.Win.ComObj, System.Types, System.Variants,
  Winapi.ActiveX, h5u.ActiveScripting.Interfaces;

var
  ClassID: TGUID;
  Engine: IActiveScript;
  ASite: IActiveScriptSite;
  Parser: IActiveScriptParse;
  ErrInfo: EXCEPINFO;
  Flags: DWORD;
  OResult: OleVariant;
  Name: WideString;
  Disp: IDispatch;
  HR: HRESULT;
begin
  // https://stackoverflow.com/questions/7491868/how-to-load-call-a-vbscript-function-from-within-c

  //CoInitializeEx(nil, COINIT_MULTITHREADED);

  OleCheck(CLSIDFromProgID(PWideChar('VBScript'), ClassID));
  Engine := CreateComObject(ClassID) as IActiveScript;

  ASite := TDummyNonInteractiveScriptSite.Create; // ODER: ASite := TDummyActiveScriptSite.Create(Self.Handle)
  OleCheck(Engine.SetScriptSite(ASite));
  OleCheck(Engine.QueryInterface(IActiveScriptParse, Parser));
  OleCheck(Parser.InitNew);

  //OleCheck(Parser.AddScriptlet(nil, PWideChar('...'), nil, nil, nil, nil, 0, 0, SCRIPTTEXT_ISVISIBLE, Name, ErrInfo));
  {or}
  //OleCheck(Parser.ParseScriptText(PWideChar('...'), nil, nil, nil, 0, 0, ..., nil, ErrInfo));
  {or}
  //if Failed(Parser.ParseScriptText(PWideChar('...'), nil, nil, nil, 0, 0, ..., nil, ErrInfo)) then
  // raise Exception.CreateFmt('Error $%x: %s', [ErrInfo.scode, ErrInfo.bstrDescription]);
  {or}
  //HR := Parser.ParseScriptText(PWideChar('...'), nil, nil, nil, 0, 0, ..., nil, ErrInfo);
  //if Failed(HR) then
  // raise Exception.CreateFmt('Error $%x %s'#10'$%x: %s', [HR, SysErrorMessage(Cardinal(HR)), ErrInfo.scode, ErrInfo.bstrDescription]);

  //HR := Parser.ParseScriptText(PWideChar('WScript.Echo "abc"'), nil, nil, nil, 0, 0, SCRIPTTEXT_ISVISIBLE, @OResult, ErrInfo);
  HR := Parser.ParseScriptText(PWideChar('set fso = CreateObject("Scripting.FileSystemObject")'#10'set stream = fso.GetStandardStream(1)'#10
    + 'stream.WriteLine("This will go to standard output.")'), nil, nil, nil, 0, 0, SCRIPTTEXT_ISVISIBLE, @OResult, ErrInfo);
  if Failed(HR) then
    raise Exception.CreateFmt('Error $%x %s'#10'$%x: %s', [HR, SysErrorMessage(Cardinal(HR)), ErrInfo.scode, ErrInfo.bstrDescription]);

  HR := Parser.ParseScriptText(PWideChar('a = 123'), nil, nil, nil, 0, 0, SCRIPTTEXT_ISVISIBLE, @OResult, ErrInfo);
  if Failed(HR) then
    raise Exception.CreateFmt('Error $%x %s'#10'$%x: %s', [HR, SysErrorMessage(Cardinal(HR)), ErrInfo.scode, ErrInfo.bstrDescription]);
  //
  HR := Parser.ParseScriptText(PWideChar('a * 2 + 3'), nil, nil, nil, 0, 0, SCRIPTTEXT_ISEXPRESSION, @OResult, ErrInfo);
  if Failed(HR) then
    raise Exception.CreateFmt('Error $%x %s'#10'$%x: %s', [HR, SysErrorMessage(Cardinal(HR)), ErrInfo.scode, ErrInfo.bstrDescription]);
  Writeln('Result = ' + VarToStrDef(OResult, '(NULL)'));
  //
  HR := Parser.ParseScriptText(PWideChar('MsgBox "Hello World! The current time is " & Now'), nil, nil, nil, 0, 0, SCRIPTTEXT_ISVISIBLE, @OResult, ErrInfo);
  if Failed(HR) then
    raise Exception.CreateFmt('Error $%x %s'#10'$%x: %s', [HR, SysErrorMessage(Cardinal(HR)), ErrInfo.scode, ErrInfo.bstrDescription]);

  // Engine.GetScriptDispatch(nil, Disp);

  //CoUninitialize;
end;
Müsste jemand das Script aber nochmal testen ... kann sein, dass SetScriptSite nötig ist und man sich noch ein kleines IActiveScriptSite basteln muß.
Ja, ein IActiveScriptSite muß bereitgestellt werden, aber die Funktionen können quasi leer sein (einfach nur überall Result jeweils mit S_OK, S_FALSE usw. beglücken)
Hab dafür zwei Dummy-Interfaces in die Interface-Unit gepackt und rechts noch Knöpfe "Native-API" in die Demo-/Testanwendung.

Sollen die Scripte auch Interaktiv sein dürfen, dann muß auch IActiveScriptSiteWindow implementiert sein (und OK sagen), sonst raucht es z.B. bei einem MsgBox "peng" mit einer Exception "Erlaubnis verweigert".
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 7. Nov 2023 um 07:09 Uhr)
  Mit Zitat antworten Zitat