我正在升级一个带有com自动化接口的delphi软件项目,以简化一些批处理任务(通过WSH-Scripting)。这本身很容易……然而,该软件的大多数"实际"用户不需要(甚至不知道)这个接口,我想让他们免于注册com服务器或弹出错误消息,当程序无法启动com服务器(目前该软件没有安装程序-它只是复制和走。注册任何东西对用户来说都是一个额外的步骤。它是内部的,所以客户已经习惯了…)。
这里是实际的问题:我可以通过编程找出当前运行该软件的用户是否有足够的权利注册COM服务器,然后(如果没有)避免尝试创建服务器吗?我希望当用户没有足够的权限时,自动化服务器就不存在(没有错误消息)。
我试着在TAutoObjectFactory.Create(...)
周围添加一个try-catch,但这并不能防止错误。添加启用服务器的命令行参数也不起作用,因为从脚本创建自动化对象将启动没有该参数的程序,因此也不会创建服务器。
为了解决这个问题,我使用从TAutoObjectFactory
继承的TMyAutoObjectFactory
对象,并使用沉默的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.
这将使错误沉默,但你仍然需要以管理权限运行一次应用程序,或者让安装程序添加所需的注册表项。
我通过将delphi的comserve -unit复制到项目中,并在Comserver.Initialize
方法(-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;
注意:只有外侧的试块是我的;其余部分是Delphi5附带的原始版本。这似乎抑制了错误(之前有人问:是的,我知道服务器没有运行,但这是期望的结果;至少程序启动-我不明白为什么整个程序无法启动,如果服务器不能注册)。
PS:我没有把这个设置为可接受的答案,因为它"感觉"太像黑客了,因为它留下了一半初始化的ComServer,我不知道这是否可能有任何副作用…