Delphi 将字符串参数传递给 IDispatch.Invoke

标签 delphi variant iactivescript

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

function test2(n)
  MsgBox n
  test2 = n
end function

VBScript 代码加载正常,传递整数作为参数工作正常,但是当传递字符串参数时,我发现只有字符串的前半部分进入脚本。德尔福代码:

procedure TForm1.Button4Click(Sender: TObject);
var
  Disp: IDispatch;
  Res: OleVariant;
  DispParams: TDispParams;
  s: string;
  n: Integer;
  v: Variant;
  Arg: array of TVariantArg;
begin
  OleCheck(FScript.GetScriptDispatch(nil, Disp));

  s := 'test2';

  OleCheck(Disp.GetIDsOfNames(GUID_NULL, @s, 1, 1033, @n));

  v := VarArrayOf(['1234567890']);

  SetLength(Arg, VarArrayHighBound(v, 1) - VarArrayLowBound(v, 1) + 1);

  arg[0].vt := VT_BSTR;
  arg[0].bstrVal := PWideChar(VarToStr(v[0])); //passes first half of string only
//  arg[0].bstrVal := SysAllocString(PWideChar(VarToStr(v[0]))); //passes complete (copy of) string
  end;

  DispParams.rgvarg := @Arg[0];
  DispParams.rgdispidNamedArgs := nil;
  DispParams.cArgs := 1;
  DispParams.cNamedArgs := 0;
//at this point, debugger shows no difference, bstrVal holds full string
  OleCheck(Disp.Invoke(n, GUID_NULL, 1033, DISPATCH_METHOD, DispParams, @res, nil, nil));
end;

MsgBox 显示 12345。也尝试过其他字符串、其他字符串长度,但总是只前半部分。

谁能解释一下这个问题?

最佳答案

与 COM 交互时,您需要使用 WideString (COM BSTR 字符串的包装器)而不是使用 string (又名 UnicodeString),例如:

procedure TForm1.Button4Click(Sender: TObject);
var
  Disp: IDispatch;
  Res: OleVariant;
  DispParams: TDispParams;
  s: WideString;
  n: Integer;
  v: Variant;
  Arg: array of TVariantArg;
begin
  OleCheck(FScript.GetScriptDispatch(nil, Disp));

  s := 'test2';
  OleCheck(Disp.GetIDsOfNames(GUID_NULL, @s, 1, 1033, @n));

  v := VarArrayOf(['1234567890']);

  SetLength(Arg, VarArrayHighBound(v, 1) - VarArrayLowBound(v, 1) + 1);

  s := VarToWideStr(v[0]);
  arg[0].vt := VT_BSTR;
  arg[0].bstrVal := PWideChar(s);
  //arg[0].bstrVal := SysAllocString(PWideChar(s));

  DispParams.rgvarg := @Arg[0];
  DispParams.rgdispidNamedArgs := nil;
  DispParams.cArgs := 1;
  DispParams.cNamedArgs := 0;

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

  //SysFreeString(arg[0].bstrVal);
end;

关于Delphi 将字符串参数传递给 IDispatch.Invoke,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72439138/

相关文章:

javascript - IE 9's Javascript engine (code-named "Chakra 的 ProgId 或 CLSID 是什么”)

delphi - TObject 包含哪些数据?

delphi - 重写 Delphi 表单构造函数和使用它的 OnCreate 事件是否存在问题?

Delphi:当组件放置在表单上时,错误的单元添加单元到源文件的使用子句

c++ - 如何(优雅地)读取列具有不同类型的文件并适本地存储列?

c++ - 我可以将 std::variant<Ts...> 分配给/构造 std::variant<Ts..., Ys...> 吗?

c++ - COM:创建 BSTR 的 SafeArray 的访问冲突

delphi - 是否可以在任务之间发送消息(OmniThreadLibrary)?

c++ - IActiveScript 分析 - 查看脚本源