在C#中动态加载和使用COM对象

4
我有一个C#项目,我想要访问 MS Outlook,如果它安装在客户端机器上。"访问Outlook"部分已经通过引用 Outlook COM 对象完成,并从那里继续。我的问题现在是“如果已安装”的部分。目前,在没有安装 Outlook 的机器上,我的项目无法编译,因此我认为我将不得不不引用 Outlook 组件,并在检测到 Outlook 存在后动态加载和使用它,但我还没有找到方法来实现这一点。我是正确的吗?有人知道如何做吗?
谢谢。
编辑:已解决。遵循 Hans Passant 在其中一条评论中提供的关于使用 Office PIAs 的建议,被证明是最方便的方法。我在没有 Office 的机器上遇到了一些困难,但通过 问题的接受答案克服了这些困难。

你好Boris,我担心你混淆了开发环境和部署环境。在开发中,你应该引用正确的程序集,并且这些程序集应该可用于构建代码。在生产环境中,你不必构建任何东西,但你的程序将需要安装Outlook。 - Davide Piras
@Davide Piras:我认为你过度使用了你的编辑和重新标记权限... - Daniel Hilgarth
我进行了一些标签清理,因为例如在这种情况下,我相信我们不需要同时使用com和com-interop标签...如果我错了,对不起Boris。 - Davide Piras
@Davide Piras:没问题。我不完全确定我最初给了什么标签,但我认为我没有使用com-interop,因为我也不觉得两者都需要。我不反对当前的四个标签,但我想添加一些标签,表明这个问题特别涉及基于可用性加载COM对象。不过我不知道应该使用哪个标签。 - Boris
2个回答

2
你在没有安装Outlook COM对象的机器上无法编译汇编代码,但这并不意味着你的应用程序在没有Outlook的机器上完全无法运行 - 只是尝试创建或使用Outlook COM对象将会导致失败/异常抛出。
根据这个问题,检测COM对象是否存在的最佳方法就是尝试实例化它,并在未安装时捕获结果异常。

谢谢。我不太确定COM对象实际上是何时加载的,但我模糊地认为对象的代码将在程序加载时加载,而不是在对象实例化时,所以我不确定该如何捕捉它。只是为了确保,COM对象和程序集是否仅在使用其类之一时才被加载,这种行为是否标准? - Boris
2
你绝对可以这样做,这就是类型库的作用。这非常重要,例如你可能不想针对你已安装的版本进行目标定位。从Office安装目录中复制MSOutl.olb到你的项目目录中。或者安装Office PIA。 - Hans Passant
@Hans Passant:谢谢,我最终采纳了您的建议。如果您把它作为答案,我会接受它。 - Boris

1

根据Hans Passant的建议,我现在用我的解决方案详细回答自己的问题。我能够在没有安装Office的计算机上编译和运行我的项目。主要问题是让Visual Studio知道可以从COM对象中期望哪个接口。这是通过找到Outlook的主要接口程序集(PIA)文件来解决的。该过程在this问题中更好地描述,但简短的故事是我已经在计算机上拥有Office PIAs,位于此位置:

C:\Program Files\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA

我使用的是VS2010专业版,不知道其他版本是否包含这些文件。然后,我只需要将相关文件复制到我的项目源文件夹中,将其包含在我的项目和源代码控制中,并引用它。之后,我就能在我的项目中使用Outlook COM类型并且编译时不会出错。我还能在没有安装Office的情况下运行我的项目。这是通过尝试实例化相关的COM对象,并在未安装Office时捕获异常来实现的。以下示例代码显示了如何实现:

using Outlook = Microsoft.Office.Interop.Outlook;

namespace Foo
{
    public class Bar
    {
        public void Quux()
        {
            try
            {
                // try to instantiate outlook COM object.
                Outlook.Application outlookApp = new Outlook.Application();

                // if it works, fine. Proceed
                ...
            }
            // If we catch a COMException, assume no office installed. Deal accordingly.
            catch (System.Runtime.InteropServices.COMException)
            {
                ...
            }
        }
    }
}

你甚至可以在不使用 using Outlook = Microsoft.Office.Interop.Outlook; 的情况下工作。我一直在使用 Excel 和 Access 进行这样的操作。这样就完全不需要安装 MS Office。当然,你必须要完全盲目地工作。没有代码自动完成(针对 Outlook 对象),也没有有用的编译错误提示等。 - Bitterblue

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