MAPI链接静态库(LNK2019:未解析的外部符号)

时间:2018-04-13 14:43:26

标签: c# c++ c++-cli mapi

我尝试使用Visual Studio 2017来使用Microsoft的MAPI(扩展MAPI)。

首先,我创建了一个包含3个项目的解决方案:

  1. Visual C ++ - Windows桌面 - 静态库
  2. Visual C ++ - CLR - 类库
  3. Visual C# - 经典Windows桌面 - WPF-App
  4. (1)设置如下:

    stdafx.h中

    #pragma once
    
    #include "targetver.h"
    
    #define WIN32_LEAN_AND_MEAN
    
    // Not auto generated
    #define DLLEXPORT __declspec(dllexport)
    

    InstanceManager.h

    #pragma once
    
    namespace NativeWrapper
    {
        class DLLEXPORT InstanceManager
        {
        public:
            InstanceManager();
            int Init();
            void UnInit();
            ~InstanceManager();
        private:
            bool _Initialized;
        };
    }
    

    InstanceManager.cpp

    #pragma once
    #include "stdafx.h"
    #include "InstanceManager.h"
    
    namespace NativeWrapper
    {
        InstanceManager::InstanceManager()
        {
            _Initialized = false;
        }
    
        int InstanceManager::Init()
        {
            if (!_Initialized)
            {
                MAPIINIT init = {
                    MAPI_INIT_VERSION,
                    MAPI_MULTITHREAD_NOTIFICATIONS
                };
                return MAPIInitialize(&init);
            }
        }
    
        void InstanceManager::UnInit()
        {
            if (_Initialized)
            {
                MAPIUninitialize();
            }
        }
    
        InstanceManager::~InstanceManager()
        {
            UnInit();
        }
    }
    

    我还下载了MAPI开发所需的标题并引用了它 通过将相应的路径(C:\Office 2010 Developer Resources\Outlook 2010 MAPI Headers)添加到其他包含目录。

    (2)设置如下:

    InstanceManager.h

    #pragma once
    
    #include "..\StaticLib1\NativeInstanceManager.h"
    
    namespace MAPIManaged
    {
        ref class InstanceManager
        {
        public:
            InstanceManager();
            ~InstanceManager();
            int Init();
            void UnInit();
        private:
            NativeWrapper::InstanceManager* _NativeObject;
        };
    }
    

    InstanceManager.cpp

    #include "stdafx.h"
    #include "InstanceManager.h"    
    
    namespace MAPIManaged
    {
        InstanceManager::InstanceManager()
        {
            _NativeObject = new NativeWrapper::InstanceManager();
        }
    
        InstanceManager::~InstanceManager()
        {
            delete _NativeObject;
        }
    
        int InstanceManager::Init()
        {
            return _NativeObject->Init();
        }
    
        void InstanceManager::UnInit()
        {
            _NativeObject->UnInit();
        }
    }
    

    还有(1)项目参考。 我通过右键单击项目2并添加了项目1来完成它。

    (3)设置如下:

    using System.Windows;
    
    namespace WpfApp1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
               var obj = new MAPIManaged.InstanceManager();
               obj.Init();
            }
        }
    }
    

    还有(2)项目参考。 我通过右键单击项目3并添加了项目2来完成它。

    错误

    虽然我引用了静态库,但我收到以下错误:

    错误1:MapUninitialize链接错误

    Error LNK2019 unresolved external symbol "_MAPIUninitialize@0"
        in function ""public: void __thiscall NativeWrapper::InstanceManager::UnInit(void)" (?UnInit@InstanceManager@NativeWrapper@@QAEXXZ)".
    ClassLibrary1   PATH\WrapNative\ClassLibrary1\StaticLib1.lib(InstanceManager.obj)   1   
    

    错误2:MapInitialize链接错误

        Error LNK2019 unresolved external symbol "_MAPIInitialize@4"
    in function ""public: int __thiscall NativeWrapper::InstanceManager::Init(void)" (?Init@InstanceManager@NativeWrapper@@QAEHXZ)".
    ClassLibrary1   PATH\WrapNative\ClassLibrary1\StaticLib1.lib(InstanceManager.obj)   1   
    

2 个答案:

答案 0 :(得分:1)

您永远不应该静态链接到任何MAPI函数 - 您必须首先找到正确的MAPI dll并使用LoadLibrary / GetProcAddress。

查看MFCMAPI source code有关如何完成此操作的示例。

答案 1 :(得分:0)

扩大Dmitry的答案-唯一的mapi32.lib版本存在错误(缺少导出,错误的参数数量和类型等),并且十年来一直没有Microsoft的支持。 MSDN文章Link to MAPI functions对此进行了深入讨论,并提供了许多链接到MAPI的选项,所有这些选项归结为: 1-找到正确的要加载的MAPI DLL,这很简单,涉及到对FGetComponentPath的调用以找到正确的MAPI实现。实际上,您可以通过仅链接到系统mapi32.dll(本身是存根)来稍微简化此步骤,但是您会错过Outlook MAPI提供的未在系统存根中公开的导出。 2-找到后,使用LoadLibrary和GetProcAddress链接到导出。

本文还链接到Microsoft推荐的MAPIStubLibrary,其中封装了上述逻辑。最好使用此存根库代替手动滚动位置和链接逻辑。

免责声明:我是Microsoft员工,是MFCMAPI的作者,还是Outlook开发团队与MAPI Stub库的合著者。