当调用OLE字CentimetersToPoints的时候未指定的错误 [英] Unspecified error when calling Word CentimetersToPoints via OLE

查看:650
本文介绍了当调用OLE字CentimetersToPoints的时候未指定的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当德尔福(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆