通过 Windows 服务运行时,操作不可用(来自 HRESULT 的例外:0x800401E3 (MK_E_UNAVA



我尝试从Windows服务挂钩到Outlook应用程序,但出现异常 操作不可用(HRESULT的异常:0x800401E3(MK_E_UNAVAILABLE))这是我的代码。

   public void ItemSendEvent()
    {
        try
        {
           if (Process.GetProcessesByName(ApplicationConstants.OUTLOOK_PROCESS_NAME).Count() > 0)
                {
                    // If so, use the GetActiveObject method to obtain the process and cast it to an Application object.
                    outlookApplication = Marshal.GetActiveObject(ApplicationConstants.OUTLOOK_APPLICATION_NAME) as Microsoft.Office.Interop.Outlook.Application;
                    Microsoft.Office.Interop.Outlook.NameSpace nameSpace = outlookApplication.GetNamespace(ApplicationConstants.OUTLOOK_NAME_SPACE);
                    nameSpace.Logon("", "", Missing.Value, Missing.Value);
                    nameSpace = null;
                    outlookApplication.ItemSend += outlookApplication_ItemSend;
                }
                log.Info("Outlook Item Send event registered successfully.");
        }
        catch (System.Exception ex)
        {
            log.Error("Exception occurred while registering Outlook Item Send event. " + ex.Message);
        }
    }

但是当我通过 Windows 表单应用程序启动它时,相同的代码可以正常工作。 我浏览了一些网站,他们说 Outlook 对象不在 ROT 表中。 解决方案是什么。

Outlook 或任何其他 Office 应用无法在 Windows 服务中运行,即使你的服务以交互式用户身份运行也是如此。只有扩展 MAPI(仅限 C++ 或 Delphi)或扩展 MAPI 包装器(如 Redemption)(我是它的作者 - 它的 RDO 系列对象)才能在服务中使用。

在您的特定情况下,您似乎正在尝试捕获Application.ItemSend事件。绝对没有理由为此创建Windows服务。创建一个 COM 加载项 - 只要 Outlook 本身在同一安全上下文中的同一进程中运行,它就会由 Outlook 加载并运行。

两个常见问题可能会导致此问题。

第一种情况是,您在管理员模式下运行Visual Studio,并且从VS中启动程序,而Office应用程序则不是。若要解决此问题,还需要在管理员模式下使用提升的权限运行 Office 应用程序。

第二个可能是由于调用 Marshal.GetActiveObject(...) 时应用程序未完全启动/加载。

旧,但仍然很重要。

尝试使用 MS 示例访问 Outlook 数据时,我遇到了此错误。

处理 Try/Catch 块中的错误并提供更新 Outlook 的选项可以解决问题:

const int ERROR_HRESULT_0x800401E3_MK_E_UNAVAILABLE= -2147221021;
        Outlook.Application application = null;
        // Check whether there is an Outlook process running.
        if (Process.GetProcessesByName("OUTLOOK").Any())
        {
            try
            {
                // If so, use the GetActiveObject method to obtain the process and cast it to an Application object.
                application = Marshal.GetActiveObject("Outlook.Application") as Outlook.Application;
                }
            }
            catch (Exception ex)
            {
                //This is the branch where you can get correctly the current Outlook instance
                if (ex.HResult == ERROR_HRESULT_0x800401E3_MK_E_UNAVAILABLE)
                {
                    application = new Outlook.Application();
                }
            }
        }
        else
        {
            application = new Outlook.Application();
        }

尽管newing技巧起作用,但不会创建其他Outlook实例,因为Outlook的行为类似于Singleton。

我只在安装了Office 365 64位的情况下对其进行了测试。

你不需要将你的应用程序作为一个服务来让它在后台......

如果您的 winform 运行良好,只需将您的 winform 放在后台运行在系统托盘上

即可

最新更新