C#控制台应用程序使用Interop.domino.dll - 作为计划任务运行时失败

4
我编写了一个C#控制台应用程序,使用Interop.domino.dll程序集与domino/notes交互来创建、更新和删除文档。当手动通过cmd提示符或通过Visual Studio运行应用程序时,它可以成功运行。然而,当我们尝试将应用程序设置为计划任务(在域服务帐户下运行)时,它会失败,并显示以下错误:
System.Runtime.InteropServices.COMException: 由于以下错误,检索组件CLSID {29131539-2EED-1069-BF5D-00DD011186B7}的COM类工厂失败:80004005未指定的错误(Exception from HRESULT:0x80004005(E_FAIL))。
当我们尝试使用Interop.domino.dll中的对象时(特别是尝试创建NotesSession对象实例时),就会出现此错误:
ISession notesSession = new NotesSession();
经过一些调查,我发现interop程序集需要与桌面交互,如果我们使用服务帐户登录运行计划任务,则计划任务将失败。当以服务帐户身份登录时,您可以看到应用程序在运行时会弹出svchost.exe窗口,这就是它需要桌面的原因。
但是,让服务帐户始终登录机器不是可接受的解决方案,因为这意味着每次服务器重新启动时都必须重新登录该帐户。还存在一些安全问题,关于允许服务帐户登录机器。
因此,我想知道是否有人对如何解决这个问题有任何建议?是否有一种方法可以抑制程序集尝试显示的任何UI?或者,有没有人建议一个类似于计划任务的替代方案,可以实现类似的结果。我们需要做的是:
在设置的间隔(例如-每天一次/每小时一次)运行应用程序
理想情况下,以域服务帐户身份运行(而不是本地系统帐户)
无需让服务帐户登录到机器/UI元素从Interop.domino.dll中抑制运行
我们考虑编写一个类似的应用程序,利用notes web服务而不是Interop assmebly,并将沿着这条路走,如果我们不能让控制台应用程序作为计划任务运行。然而,如果可能的话,我们想利用我已经编写的内容。
更新01/05/12
我已经尝试了根据@dna-man解决方案设置NOTESNTSERVICE OS环境变量。但是,这并没有解决问题。
目前,我们已将应用程序设置为在允许与桌面交互的本地系统帐户下运行的Windows服务。这并不理想,因为它不允许我们轻松地安排它,并且它没有在域服务帐户下运行,但应用程序可以工作,所以我们现在将采用这种方法。

有一个答案建议采用这种方法,但似乎已被删除,因此我无法将其标记为正确答案。我可能会让问题保持一段时间,看看是否有其他建议。


1
如果你有Domino服务器,为什么不运行本地Notes代理? - leyrer
1
这与互操作程序集无关,它只包含声明而没有代码。请联系IBM获取支持。 - Hans Passant
@leyrer - 如果我们无法让C#应用程序正常工作,我们可能会走上编写笔记代理的道路来执行任务。然而,由于在应用程序开发的后期才发现了这个问题,如果可能的话,我们希望利用已经编写的内容。 - b_dialog
如果您通过cmd提示手动运行它(第一次),是否会提示输入Notes密码? - leyrer
@leyrer - 不,我们手动运行时没有得到那个提示。然而,在初始化(在这种情况下只是密码)/ InitializeUsingNotesUserName 方法中,我们提供了用户名和密码。 - b_dialog
@HansPassant - 我在最初查看时错过了您的评论。您正确指出,Interop程序集不包含任何代码。实际上是Lotus Domino对象(domobj.tlb)引起了问题,Interop程序集只是其包装器。至少,这是我的理解。 - b_dialog
3个回答

1

如果您的代码正在 Domino 服务器上运行,您必须确保设置了操作系统环境变量 NOTESNTSERVICE=1。您可以在 Lotus C API 文档中了解更多关于此环境变量的信息,但是当作为服务运行时,它也适用于 COM API。早在2003年,我创建了一个VB.NET应用程序,必须作为服务运行,并设置了这个环境变量。如果没有设置,服务将在我注销机器后立即停止工作。为了确保未来安装服务时没有人忘记设置此环境变量,我只需让我的服务管理器启动代码直接在启动时使用 VB.NET 调用 SetEnvironmentVariable 设置此环境变量。它必须在创建 Domino 会话对象之前设置。


谢谢,我会将这个作为潜在的解决方案来考虑。我们使用的是定时任务而不是服务,但从你的解释中,我猜想设置环境变量也可能适用于定时任务。 - b_dialog
我研究了一下,设置这个环境变量并没有解决问题。也许需要设置它,但看起来它并不能抑制与桌面交互的需求。 - b_dialog

0

最终,我稍微修改了应用程序,将其设置为在本地系统帐户下运行的Windows服务,并允许与桌面进行交互。虽然这不是理想的解决方案,因为它不允许我们轻松地安排计划并且不是在域服务帐户下运行。但是,这种方法允许应用程序在不需要始终登录帐户的情况下运行,并允许显示Interop UI元素(从而避免错误)。

要安排Windows服务以固定间隔执行任务(我将其设置为每天一次),我使用了此处提出的计时器解决方案。


0

很难确切地说为什么,但我认为它无法读取Lotus互操作类的注册表信息。显然,这些条目是存在的,否则在手动运行时不会起作用。所以让我们考虑其他可能性。

我甚至不知道这是否可能,但是你的应用程序在手动运行时是32位的,但在计划安排时是64位的吗?IBM不支持Domino COM类在Win64上使用,而且我几乎确定其第一个症状就是注册表

一个更普通的可能性是服务帐户没有访问机器上Notes/Domino安装的注册表条目的权限,可能是因为软件是在特定用户帐户下安装的。


我还没有查看服务帐户的注册表权限,但我不确定这解释了为什么当计划任务正在运行的服务帐户登录到机器时它可以正确运行。如果服务帐户没有读取注册表的权限,那么即使服务帐户登录到机器上,它也可能会失败。因此,似乎这不是一个注册表权限问题。 - b_dialog
关于32位与64位的建议,当服务账户登录到机器上时,预定任务确实可以工作,它并没有完全失败。如果是由于这个原因,那么它可能不会一直工作。因此,我认为我们可以排除这种可能性。 - b_dialog
我仍然相信这是一个注册表读取错误,我能想到的最好答案是,由于某种原因,域服务帐户除非实际登录,否则没有权限。机器上安装了任何反恶意软件/防火墙/入侵保护软件吗?从谷歌错误代码0x80004005,我看到在一些情况下涉及到这种类型的东西。我唯一的其他建议是使用域服务帐户重新安装Domino(如果它是在不同的帐户下安装的),或者如果您有活动支持合同,则致电IBM。 - Richard Schwartz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接