通过Windows服务运行时,操作不可用(来自HRESULT的异常:0x800401E3(MK_E_UNAVAILABLE))?

时间:2016-06-02 10:58:56

标签: c# .net outlook windows-services ms-office

我尝试从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 Form Application启动它时它的工作正常。我经历了一些网站,他们说Outlook对象不在ROT表中。什么是解决方案。

4 个答案:

答案 0 :(得分:4)

即使您的服务作为交互式用户运行,Outlook或任何其他Office应用也无法在Windows服务中运行。只能在服务中使用扩展MAPI(仅限C ++或Delphi)或扩展MAPI包装,如Redemption(其RDO系列对象)。

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

答案 1 :(得分:2)

两个常见问题可能导致这种情况。

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

第二种情况可能是由于您致电Marshal.GetActiveObject(...)时应用程序未完全启动/加载。

答案 2 :(得分:0)

您不需要将您的应用程序作为服务来获取它的背景......

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

答案 3 :(得分:0)

旧但仍然重要的线程。

我遇到这种错误,尝试使用MS example访问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();
        }

尽管具有新的技巧,但由于Outlook的行为类似于Singleton,因此不会创建其他Outlook实例。

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