gpt4 book ai didi

delphi - 通过 OLE 调用 Word CentimetersToPoints 时出现未指定错误

转载 作者:行者123 更新时间:2023-12-03 15:30:46 25 4
gpt4 key购买 nike

以下代码在 Delphi (XE) 中执行时失败,并在 CentimetersToPoint 调用上出现 OLE 800040005“未指定”错误,类似的 VBS 或 VBA 版本通过

var w : OleVariant;

w := CreateOleObject('Word.Application');
w.Visible := true;
Writeln(w.CentimetersToPoints(2.0));

FWIW 类型库给出

/ [id(0x00000173), helpcontext(0x09700173)]
// single CentimetersToPoints([in] single Centimeters);

默认情况下,Delphi 仅将浮点值作为 Double 传递,因此我尝试直接调用 IDispatch.Invoke 并将参数作为 VT_R4 传递,但没有更好的结果。

编辑:可运行的 VB 版本(保存为 .vbs)

set w = CreateObject("Word.Application")
w.Visible = true
msgbox w.CentimetersToPoints(2.0)

对于可能出现的问题还有其他建议吗?

最佳答案

我最初怀疑问题在于该函数需要 Single 并且 Delphi 将您的 float 转换为其他值。当我在调试器中追踪它时,我发现传递给 Invoke 的变体的 VTypevarCurrency ,货币值为 >2。我不确定这是怎么发生的!

正如我发现的,回答这个question ,将单精度 float 放入变体中是非常棘手的。我最初怀疑您可以使用我在那里提供的解决方案来解决您的问题。

function VarFromSingle(const Value: Single): Variant;
begin
VarClear(Result);
TVarData(Result).VSingle := Value;
TVarData(Result).VType := varSingle;
end;

....

w := CreateOleObject('Word.Application');
w.Visible := true;
Writeln(w.CentimetersToPoints(VarFromSingle(2.0)));

但这也以同样的方式失败,原因我还不明白。

像您一样,我尝试使用IDispatch.Invoke调用该函数。这就是我想到的:

program SO16279098;

{$APPTYPE CONSOLE}

uses
SysUtils, Variants, Windows, ComObj, ActiveX;

function VarFromSingle(const Value: Single): Variant;
begin
VarClear(Result);
TVarData(Result).VSingle := Value;
TVarData(Result).VType := varSingle;
end;

var
WordApp: Variant;
param: Variant;
retval: HRESULT;
disp: IDispatch;
Params: TDispParams;
result: Variant;

begin
try
CoInitialize(nil);
WordApp := CreateOleObject('Word.Application');
disp := IDispatch(WordApp);

param := VarFromSingle(2.0);
Params := Default(TDispParams);
Params.cArgs := 1;
Params.rgvarg := @param;
retval := disp.Invoke(
371,//CentimetersToPoints
GUID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
Params,
@Result,
nil,
nil
);
// retval = E_FAIL

Params := Default(TDispParams);
retval := disp.Invoke(
404,//ProductCode
GUID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
Params,
@Result,
nil,
nil
);
// retval = S_OK
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.

我无法通过这种方式调用CentimetersToPoints,但可以调用ProductCode函数。

为了添加到您的成功/失败指示器集合中,当我使用 PowerShell 调用 CentimetersToPoints 函数时,我成功了。当我使用 Python 的 win32com.client 调用时,我收到 E_FAIL

显然我们缺少一些特殊的魔法成分。看来所有的 MS 工具都知道这个魔法。

我的结论是,不可能使用 Delphi 中实现的变体分派(dispatch)来调用 CentimetersToPoints。它不知道魔法,无论魔法是什么。

显然可以在IDispatch 上调用Invoke 并成功。我们可以这么说,因为其他环境也能做到这一点。所以,我还不知道缺失的魔法是什么。

如果您可以使用早期绑定(bind)的 COM,那么您就可以回避这个问题:

Writeln((IDispatch(w) as WordApplication).CentimetersToPoints(2.0));
<小时/>

好的,使用helpHans Passant ,我有一些 Delphi 代码可以调用这个函数:

program SO16279098;

{$APPTYPE CONSOLE}

uses
SysUtils, Variants, Windows, ComObj, ActiveX;

function VarFromSingle(const Value: Single): Variant;
begin
VarClear(Result);
TVarData(Result).VSingle := Value;
TVarData(Result).VType := varSingle;
end;

var
WordApp: Variant;
param: Variant;
retval: HRESULT;
disp: IDispatch;
Params: TDispParams;
result: Variant;

begin
try
CoInitialize(nil);
WordApp := CreateOleObject('Word.Application');
disp := IDispatch(WordApp);

param := VarFromSingle(2.0);
Params := Default(TDispParams);
Params.cArgs := 1;
Params.rgvarg := @param;
retval := disp.Invoke(
371,//CentimetersToPoints
GUID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD or DISPATCH_PROPERTYGET,
Params,
@Result,
nil,
nil
);
Writeln(Result);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.

出于未知原因,您需要包含 DISPATCH_PROPERTYGET 以及 DISPATCH_METHOD

question that I asked可能会使这个问题重复。所以,我投票结束。

关于delphi - 通过 OLE 调用 Word CentimetersToPoints 时出现未指定错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16279098/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com