【问题标题】:Hiding COM-Server OLE error message when user does not have sufficient rights当用户没有足够的权限时隐藏 COM-Server OLE 错误消息
【发布时间】:2014-06-19 09:40:35
【问题描述】:

我正在升级一个带有 COM 自动化接口的 Delphi 软件项目,以简化一些批处理任务(通过 WSH 脚本)。这本身很容易......但是,该软件的大多数“实际”用户不需要(甚至不知道)这个界面,我想让他们免于注册 COM-Server 或错误消息弹出,当程序无法启动 com 服务器时(目前该软件没有安装程序 - 它只是复制和运行。注册任何东西对用户来说都是一个额外的步骤。它是内部的,所以客户端已经习惯了。 ..)。

这是一个实际的问题:我能否以编程方式找出运行该软件的当前用户是否有足够的权限来注册 COM 服务器,然后(如果没有)避免尝试创建服务器?我想要一种行为,当用户没有足够的权限时,自动化服务器不存在(没有错误消息)。

我尝试在TAutoObjectFactory.Create(...) 周围添加一个try-catch,但这并不能防止错误。添加启用服务器的命令行参数也不起作用,因为从脚本创建自动化对象将在没有该参数的情况下启动程序,因此也不会创建服务器。

【问题讨论】:

  • 您始终可以使用 PerUserRegistion 而不是全局。它不需要管理员权限。
  • 你为什么要注册服务器。使用免费注册 COM。
  • @DenisAnisimov 在 Delphi5 中似乎不存在
  • @DavidHeffernan 我试过了 - 但无法让它工作......而且我在某处读到无注册 COM 并不真正适用于脚本。
  • @FrankB Delphi 5 没有定义 COM。 COM 是系统的一部分。如果你想注册每次使用,就这样做。如果 Emba 类不提供该功能,请自己编写。如果您必须使用 15 年历史的工具,请确保它已经过时 15 年。确实希望必须编写代码来弥补这一点。

标签: windows com automation delphi-5 com-server


【解决方案1】:

为了解决这个问题,我使用了一个继承自 TAutoObjectFactoryTMyAutoObjectFactory 对象,并使用静默 try/except 子句覆盖了 UpdateRegistry 方法,并更新了底部的初始化部分以使用它。像这样:

type
  TMyAutoObjectFactory=class(TAutoObjectFactory)
  public
    procedure UpdateRegistry(Register: Boolean); override;
  end;

{ TMyAutoObjectFactory }

procedure TMyAutoObjectFactory.UpdateRegistry(Register: Boolean);
begin
  try
    inherited;
  except
    //silent
  end;
end;

initialization
  TMyAutoObjectFactory.Create(ComServer, TMyObjectSomething, Class_MyObjectSomething, ciMultiInstance, tmApartment);
end.

这将使错误消失,但您仍需要以管理权限运行应用程序一次,或让安装程序添加所需的注册表项。

【讨论】:

  • 我不太明白这是在做什么。您要么需要写入注册表,要么不需要。如果你这样做了,那你怎么能默默地继续呢?
  • @DavidHeffernan 关键是不要在没有足够权限的情况下注册,但要让程序可用 - 然后 COM-Automation 不可用;但这在我的上下文中是可以的。然而,这个解决方案并没有做到这一点——至少在 Delphi5 中没有。
  • @David 如果可能的话,它会尝试注册,如果不可能的话,它会静默失败——就像 OP 要求的那样。这不是我会使用的解决方案,但我不明白为什么它在这种特殊情况下不应该有效。
  • @SpeedFreak 因为仍然抛出异常并阻止程序正常启动。实际的执行发生在 ComServer.Initialize 中(不在 AutoObjectFactory 中)。也许这在不同版本的 Delphi 中有所不同......
  • @FrankB 如果没有关于错误的详细信息,我将不得不猜测,所以我猜它不是 COM 服务器的注册失败,而是类型库的注册。您如何启动注册?您是否尝试过直接在 try...except 中调用 ComServer.UpdateRegistry(True)?
【解决方案2】:

我通过将 Delphis comserv-unit 复制到项目中解决了这个问题,并在 Comserver.Initialize-method(-body) 周围放置了一个 try-except 块,因为事实证明异常发生在那里(而不是在注册时TAutoObjectFactory):

PROCEDURE TComServer.Initialize;
BEGIN
  TRY
    TRY
      UpdateRegistry(FStartMode <> smUnregServer);
    EXCEPT
      ON E: EOleRegistrationError DO
      // User may not have write access to the registry.
      // Squelch the exception unless we were explicitly told to register.
        IF FStartMode = smRegServer THEN RAISE;
    END;
    IF FStartMode IN [smRegServer, smUnregServer] THEN Halt;
    ComClassManager.ForEachFactory(Self, FactoryRegisterClassObject);
  EXCEPT
  ELSE
    FStartSuspended := true;
  END;
END;

注意:只有外面的 try-block 是我的;其余的是Delphi5(!)附带的原件。 这似乎抑制了错误(在有人问之前:是的,我知道服务器当时没有运行,但这是预期的结果;至少程序启动了——我不明白为什么整个程序无法启动,如果服务器无法注册)。

PS:我没有将此设置为可接受的答案,因为它“感觉”太像黑客,因为它留下了一半初始化的 ComServer,我不知道这是否会产生任何副作用......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    • 2011-04-01
    • 2014-09-18
    • 2011-09-03
    相关资源
    最近更新 更多