Delphi 将多个参数传递给IActiveScript IDispatch.Invoke

ykejflvf  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(142)

使用 Delphi 11.1,我想使用IActiveScript向我的应用程序添加脚本。我创建了一个小的VBScript来测试从Delphi向脚本传递多个参数:

Function TestParams(a, b, c)
  TestParams = c
End Function

VB脚本加载正常,但我有麻烦传递多个参数。 Delphi 代码:

procedure TForm1.Button14Click(Sender: TObject);
    var
      v: OleVariant;
      Disp: IDispatch;
      Arg: TArray<TVariantArg>;
      Res: OleVariant;
      DispParams: TDispParams;
      i,n: Integer;
      s: string;
    begin
      v := VarArrayOf(['Wrong...', 'huh', 'OK!']);
      s := 'TestParams';

      Memo2.Lines.Text := VarToStr(MyScriptingHost1.Run('TestParams', v));
    exit;
      OleCheck(MyScriptingHost1.FScript.GetScriptDispatch(nil, Disp));
      OleCheck(Disp.GetIDsOfNames(GUID_NULL, @s, 1, 1033, @n));

      setlength(arg, 3);

      for i := 0 to High(Arg) do
      begin
        n := High(Arg) - i;

        Arg[n].vt := VarType(v[i]);
        Arg[n].bstrVal := PWideChar(VarToWideStr(v[i]));
      end;
   //At this point, my Delphi 11.1 assignes the same value to Arg[]0, Arg[1], arg[2] 

//this works
    //Arg[0].vt := VT_BSTR;
    //Arg[0].bstrVal := 'test3';
    //
    //Arg[1].vt := VT_BSTR;
    //Arg[1].bstrVal := 'test2';
    //
    //Arg[2].vt := VT_BSTR;
    //Arg[2].bstrVal := 'test1';

      DispParams.rgvarg := @Arg[0]; //@Arg gives error
      DispParams.rgdispidNamedArgs := nil;
      DispParams.cArgs := High(Arg) + 1;
      DispParams.cNamedArgs := 0;

    //passing pointer to DispParams gives errors
      OleCheck(Disp.Invoke(n, GUID_NULL, 1033, DISPATCH_METHOD, DispParams, @res, nil, nil));
    end;

由于某些原因,多个参数对32/64位给出了不同的结果,而使用上面的代码,所有参数通常得到相同的值。非常奇怪。
更奇怪的是,运行几次有时会得到不同的结果。
以上代码在只有1个参数的情况下可以正常工作。
有谁知道这里出了什么问题吗?

ttygqcqt

ttygqcqt1#

正如我在回答your earlier question时解释的那样,在与COM接口时必须使用WideString,而不是string(即,在调用Disp.GetIDsOfNames()时)。
此外,使用VarToWideStr()会产生临时的WideString,在将Arg数组传递给Disp.Invoke()时,这些临时的WideString不再有效,因此将WideString存储在另一个数组中,以便在Invoke()退出之前将它们保留在作用域中。
试试看:

procedure TForm1.Button14Click(Sender: TObject);
var
  v: OleVariant;
  Disp: IDispatch;
  Arg: TArray<TVariantArg>;
  ArgStrs: TArray<WideString>;
  Res: OleVariant;
  DispParams: TDispParams;
  i, n: Integer;
  s: WideString;
begin
  v := VarArrayOf(['Wrong...', 'huh', 'OK!']);
  s := 'TestParams';

  //Memo2.Lines.Text := VarToStr(MyScriptingHost1.Run('TestParams', v));

  OleCheck(MyScriptingHost1.FScript.GetScriptDispatch(nil, Disp));
  OleCheck(Disp.GetIDsOfNames(GUID_NULL, @s, 1, 1033, @n));

  SetLength(Arg, 3);
  SetLength(ArgStrs, 3);

  for i := 0 to High(Arg) do
  begin
    ArgStrs[i] := VarToWideStr(v[i]);
    n := High(Arg) - i;
    Arg[n].vt := VT_BSTR;
    Arg[n].bstrVal := PWideChar(ArgStrs[i]);
  end;

  DispParams.rgvarg := @Arg[0]; //@Arg gives error
  DispParams.rgdispidNamedArgs := nil;
  DispParams.cArgs := Length(Arg);
  DispParams.cNamedArgs := 0;

  OleCheck(Disp.Invoke(n, GUID_NULL, 1033, DISPATCH_METHOD, DispParams, @res, nil, nil));
end;

相关问题