Search code examples
c#c++c++-climapi

MAPI Linking Static Library (LNK2019: Unresolved External Symbol)


I try to make use of Microsoft's MAPI (Extended MAPI) using Visual Studio 2017.

So first I created a solution with 3 projects:

  1. Visual C++ - Windows Desktop - Static Library
  2. Visual C++ - CLR - Class Library
  3. Visual C# - Classic Windows Desktop - WPF-App

(1) is set up as follows:

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();
    }
}

I also downloaded the required headers for MAPI Development and referenced them by adding the corresponding path (C:\Office 2010 Developer Resources\Outlook 2010 MAPI Headers) to the additional include directories.

(2) is setup as follows:

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();
    }
}

Also there is a Project-Reference on (1). I did it by Right-Clicking the Project 2 and added Project 1.

(3) is set up as follows:

using System.Windows;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

           var obj = new MAPIManaged.InstanceManager();
           obj.Init();
        }
    }
}

Also there is a Project-Reference on (2). I did it by Right-Clicking the Project 3 and added Project 2.

Error

Although I referenced the Static Library I get the following errors:

Error 1: MapUninitialize Linking Error

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   

Error 2: MapInitialize Linking Error

    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   

Solution

  • You should never statically link to any MAPI functions - you must first find the right MAPI dll and use LoadLibrary / GetProcAddress.

    Look at the MFCMAPI source code for an example on how this is done.