当调用OLE字CentimetersToPoints的时候未指定的错误 [英] Unspecified error when calling Word CentimetersToPoints via OLE
问题描述
当德尔福(XE),类似的VBS或VBA执行版本通过以下code失败,并在 CentimetersToPoint
调用一个OLE 800040005未指定的错误
The following code fails with an OLE 800040005 "unspecified" error on the CentimetersToPoint
call when executed in Delphi (XE), the similar VBS or VBA version passes
var w : OleVariant;
w := CreateOleObject('Word.Application');
w.Visible := true;
Writeln(w.CentimetersToPoints(2.0));
FWIW类型库给
FWIW the type library gives
/ [id(0x00000173), helpcontext(0x09700173)]
// single CentimetersToPoints([in] single Centimeters);
在默认情况下,德尔福仅通过浮动值作为双,所以我打过电话 IDispatch.Invoke
直接传递参数作为 VT_R4
,但没有更好的效果。
By default, Delphi only passes the floating values as Double, so I tried calling IDispatch.Invoke
directly and passing the argument as VT_R4
, but without better results.
编辑:VB版的作品(保存到.VBS)
edit: VB version that works (save to .vbs)
set w = CreateObject("Word.Application")
w.Visible = true
msgbox w.CentimetersToPoints(2.0)
什么可能会错误的任何其他建议?
Any other suggestions of what could be going wrong?
推荐答案
我最初怀疑的问题是,函数需要单
和Delphi的浮动转换成别的东西。当我在调试跟踪下来我发现变异传递给调用
是具有由Vtype
<$ C的$ C> varCurrency 和 2
。相当如何出现这种情况我不知道!
I initially suspected that the issue is that the function expects Single
and Delphi converts your float to something else. When I tracked it down in the debugger I find that the variant being passed to Invoke
is has VType
of varCurrency
and a currency value of 2
. Quite how that happens I'm not sure!
当我发现的,回答这个<一个href=\"http://stackoverflow.com/questions/15133496/why-does-assigning-a-single-to-a-variant-result-in-a-vardouble-variant\">question,这是令人惊讶的棘手得到一个precision浮动到一个变体。我初步怀疑,你可以用我presented有解决你的问题的解决方案。
As I discovered, answering this question, it's surprisingly tricky to get a single precision float into a variant. I initially suspected that you can use the solution I presented there to solve your problem.
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)));
但这失败也以同样的方式,其原因我还不了解。
But this fails also, in the same way, for reasons I don't yet understand.
和你一样,我尝试使用 IDispatch.Invoke
调用该函数。这是我想出了:
Like you, I tried calling the function using IDispatch.Invoke
. This is what I came up with:
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的
这种方式,但可以调用产品code
功能。
I cannot call CentimetersToPoints
this way, but can call the ProductCode
function.
要添加到您的成功/失败指标的收集,当我打电话 CentimetersToPoints的
函数中使用的PowerShell
我有成功。当我打电话使用Python的 win32com.client
,我得到 E_FAIL
。
To add to your collection of success/failure indicators, when I call CentimetersToPoints
function using PowerShell
I have success. When I call using Python's win32com.client
, I get E_FAIL
.
有,显然,我们缺少一些特殊的神奇功效。似乎所有的MS工具知道这个魔术。
There is clearly some special magic ingredient that we are missing. It seems that all the MS tools know about this magic.
我的结论是不可能使用变种派遣作为德尔福实现调用 CentimetersToPoints的
。它不知道的魔力,不管这是魔术
I conclude that it is not possible to call CentimetersToPoints
using variant dispatch as implemented in Delphi. It does not know about the magic, whatever that magic is.
这显然是可以调用调用
在的IDispatch
并取得成功。我们可以告诉大家,因为其他环境管理这样做。所以,我还不知道是失踪的法宝是什么。
It is clearly possible to call Invoke
on the IDispatch
and succeed. We can tell that because other environments manage to do so. So, what I do not know yet is what the missing magic is.
如果你可以使用早期绑定COM,那么你可以回避这个问题:
If you could use early bound COM, then you could sidestep this issue:
Writeln((IDispatch(w) as WordApplication).CentimetersToPoints(2.0));
OK,用<一个href=\"http://stackoverflow.com/questions/16285138/how-do-i-call-functions-that-receive-floating-point-values-using-idispatch-invok\">help 汉斯帕桑特的,我有一些德尔福code,它成功地调用这个函数:
OK, with the help of Hans Passant, I have some Delphi code that manages to call this function:
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
。
的<一个href=\"http://stackoverflow.com/questions/16285138/how-do-i-call-functions-that-receive-floating-point-values-using-idispatch-invok\">question我问可能使这个问题重复。所以,我投票关闭。
The question that I asked probably makes this question a duplicate. So, I'm voting to close.
这篇关于当调用OLE字CentimetersToPoints的时候未指定的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!