COM Server应用程序和GetObject - 重用正在运行的应用程序

时间:2014-03-21 16:37:14

标签: delphi com delphi-xe

我正在尝试自动化应用程序(Windows 8,Delphi XE。)对于我的测试,我正在执行以下操作:

  • 创建了一个小型测试应用程序,由表单和备忘录(Form1)
  • 组成
  • 添加了一个新的ActiveX对象,CoClass名称TestOLE,线程模式Apartment,Instancing Multiple(根据this article。)
  • 添加了一个方法Method1,只在Form1
  • 中的备忘录控件中添加了一些文字

然后我启动应用程序并双击名为test.vbs的文件,其中包含以下代码:

dim obj
set obj = GetObject("", "Project1.TestOLE")
obj.AddSomeText "Hola mundo"

当应用程序运行时,我看到创建了一个新表单,添加了文本然后退出。

我想要完成的是打开的应用程序应该更改备忘录文本。

我重复使用MultipleInstance和SingleInstance创建新项目,并且在启发式愤怒的爆发中,我甚至将线程模型更改为单一,无济于事。

我在类型库编辑器中看到两个标志:"可替换"和#34;可聚合。"但是,选择"可替换"在生成的RIDL文件中出现错误。

我已经阅读了很多关于GetObject的内容。看起来它的文档甚至是错误的(它说你可以省略第一个参数,但我发现它不起作用)。

这是在Delphi中编写可以重用的自动化服务器的正确方法吗?

1 个答案:

答案 0 :(得分:2)

嗯,我得到了它(我希望。)

阅读上述相同文章的更多内容,发现如下:

Know how to implement servers that support GetActiveObject

添加一个全局对象,并在运行对象表(ROT)中注册,可以完成将COM调用传递给正在运行的应用程序的所需任务:

项目文件:

program TestOLEProject3;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  TestOLEProject3_TLB in 'TestOLEProject3_TLB.pas',
  Unit2 in 'Unit2.pas' {TestOLE: CoClass},
  Unit3 in 'Unit3.pas';

{$R *.TLB}

{$R *.res}

begin
  Application.Initialize;
  RegisterGlobalTestOLE;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

<强> Unit2.pas:

unit Unit2;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  ComObj, ActiveX, TestOLEProject3_TLB, StdVcl;

type
  TTestOLE = class(TAutoObject, ITestOLE)
  protected
    procedure Method1; safecall;
    procedure Quit; safecall;
  end;

implementation

uses ComServ, Unit1, Unit3;

procedure TTestOLE.Method1;
begin
  Form1.Memo1.Lines.Add('Wheeee');
end;

procedure TTestOLE.Quit;
begin
  RevokeGlobalTestOLE;
end;

initialization

TAutoObjectFactory.Create(ComServer, TTestOLE, CLASS_TestOLE, ciMultiInstance,
  tmApartment);

end.

Unit3.pas (注册和取消注册全局对象的功能):

unit Unit3;

interface

procedure RegisterGlobalTestOLE;
procedure RevokeGlobalTestOLE;

implementation

uses TestOLEProject3_TLB, ComObj, ActiveX;

var
  GlobalTestOLEHandle: longint = 0;

procedure RegisterGlobalTestOLE;
var
  GlobalTestOLE: ITestOLE;
begin
  GlobalTestOLE := CoTestOLE.Create;
  OleCheck(RegisterActiveObject(GlobalTestOLE, CLASS_TestOLE,
    ACTIVEOBJECT_STRONG, GlobalTestOLEHandle));
end;

procedure RevokeGlobalTestOLE;
begin
  if (GlobalTestOLEHandle <> 0) then
  begin
    OleCheck(RevokeActiveObject(GlobalTestOLEHandle, nil));
    GlobalTestOLEHandle := 0;
  end;
end;

end.