Windows 当用户没有足够的权限时隐藏COM服务器OLE错误消息

Windows 当用户没有足够的权限时隐藏COM服务器OLE错误消息,windows,com,automation,delphi-5,com-server,Windows,Com,Automation,Delphi 5,Com Server,我正在升级一个带有COM自动化接口的Delphi软件项目,以简化一些批处理任务(通过WSH脚本)。这本身很容易。。。然而,软件的大多数“实际”用户不需要(甚至不知道)这个接口,我想让他们不用注册COM服务器或在程序无法启动COM服务器时弹出错误消息(目前该软件没有安装程序-它只是复制和运行。对用户来说,注册任何东西都是额外的一步。它是内部的,所以客户端已经习惯了…) 这里是一个实际的问题:我是否可以通过编程确定运行软件的当前用户是否有足够的权限注册COM服务器,然后(如果没有)避免尝试创建服务器

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

这里是一个实际的问题:我是否可以通过编程确定运行软件的当前用户是否有足够的权限注册COM服务器,然后(如果没有)避免尝试创建服务器?我希望出现这样的行为:当用户没有足够的权限时,自动化服务器就不在那里(没有错误消息)


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

为了解决这个问题,我使用了一个继承f的
TMyAutoObjectFactory
对象rom
TAutoObjectFactory
,只需使用无声的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.

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

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

过程TComServer.Initialize;
开始
尝试
尝试
更新注册表(FStartMode smUnregServer);
除了
在E:EOleRegistrationError DO上
//用户可能没有对注册表的写入权限。
//压制异常,除非我们被明确告知要注册。
如果FStartMode=smRegServer,则引发;
结束;
如果[smRegServer,smUnregServer]中的FStartMode,则停止;
ComClassManager.ForEachFactory(Self,FactoryRegisterClassObject);
除了
其他的
FStartSuspended:=真;
结束;
结束;
注意:只有outter try块是我的;其余的是Delphi5(!)附带的原始块。 这似乎抑制了错误(在有人问:是的,我知道服务器没有运行,但这是期望的结果;至少程序启动了-我不明白为什么整个程序无法启动,如果服务器无法注册)


附言:我并不是把这当作“感觉”的公认答案太像黑客了,因为它留下了一个半初始化的COM服务器,我不知道这是否会有任何副作用…

你总是可以使用PerUserRegistration而不是global。它不需要管理员权限。你为什么要注册服务器。使用免注册COM。@DenisAnisimov似乎不存在于Delphi5@DavidHe弗南:我试过了,但没能让它发挥作用……我也在某个地方读到,免费注册的COM实际上不能与脚本一起工作。@FrankB Delphi 5没有定义COM.COM是系统的一部分。如果你想每次使用都注册,就这样做。如果Emba课程不提供功能,就自己编写。如果你必须使用15岁的tool,你一定希望它已经过时15年了。你一定希望必须编写代码来弥补这一点。我真的不明白这是在做什么。要么你需要向注册表写入,要么你不需要。如果你需要,那么你怎么能默默地继续?@DavidHeffernan的重点是没有足够的权限就不要注册,而是拥有程序可使用的——COM自动化是不可用的,但是在我的上下文中这是可以的。但是,这个解决方案并没有实现——至少不是用Delphi 5。@戴维尝试登记如果可能的话,如果不可能的话,沉默地像OP请求的那样。这不是我要使用的解决方案,但是我看不出为什么它不应该在这个PAR中有效。特殊情况。@SpeedFreak,因为异常仍然被抛出并阻止程序正确启动。实际执行发生在ComServer.Initialize中(而不是在AutoObjectFactory中)。可能在不同版本的Delphi中有所不同…@FrankB没有关于错误的详细信息,我不得不猜测,因此我猜失败的不是COM服务器的注册,而是类型库的注册。您如何启动注册?您是否尝试调用ComServer.UpdateRegistry(True)直接在里面试试…除了?
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;