MAPI 链接静态库(LNK2019:未解析的外部符号)
MAPI Linking Static Library (LNK2019: Unresolved External Symbol)
我尝试使用 Visual Studio 2017 使用 Microsoft 的 MAPI(扩展 MAPI)。
首先我创建了一个包含 3 个项目的解决方案:
- Visual C++ - Windows 桌面 - 静态库
- Visual C++ - CLR - Class 库
- Visual C# - Classic Windows 桌面 - WPF-App
(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 开发所需的 headers 并参考
通过将相应的路径 (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) 上还有一个 Project-Reference。
我通过 Right-Clicking 项目 2 完成并添加了项目 1。
(3)设置如下:
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var obj = new MAPIManaged.InstanceManager();
obj.Init();
}
}
}
(2) 上还有一个 Project-Reference。
我通过 Right-Clicking 项目 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
您永远不应静态 link 任何 MAPI 函数 - 您必须首先找到正确的 MAPI dll 并使用 LoadLibrary / GetProcAddress。
查看 MFCMAPI source code 示例,了解如何完成此操作。
扩展 Dmitry 的回答 - mapi32.lib 的唯一版本存在错误(缺少导出、错误的参数数量和类型等)并且十多年来不受 Microsoft 支持。 MSDN 文章 Link to MAPI functions 对此进行了深入讨论,并提供了许多 linking 到 MAPI 的选项,所有这些都归结为:
1 - 找到要加载的正确 MAPI DLL,这很重要,涉及调用 FGetComponentPath 以找到 MAPI 的正确实现。实际上,您可以通过 linking 到系统 mapi32.dll(它本身是一个存根)来稍微简化此步骤,但是您将错过 Outlook 的 MAPI 提供的导出,这些导出未在系统中公开存根。
2 - 找到后,使用 LoadLibrary 和 GetProcAddress link 导出。
这篇文章也links给微软推荐的MAPIStubLibrary,其中封装了上述逻辑。最好使用此存根库而不是手动滚动位置和 linking 逻辑。
免责声明:我是一名 Microsoft 员工,是 MFCMAPI 的作者,并且是 MAPI 存根库以及 Outlook 开发团队的合著者。
我尝试使用 Visual Studio 2017 使用 Microsoft 的 MAPI(扩展 MAPI)。
首先我创建了一个包含 3 个项目的解决方案:
- Visual C++ - Windows 桌面 - 静态库
- Visual C++ - CLR - Class 库
- Visual C# - Classic Windows 桌面 - WPF-App
(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 开发所需的 headers 并参考
通过将相应的路径 (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) 上还有一个 Project-Reference。 我通过 Right-Clicking 项目 2 完成并添加了项目 1。
(3)设置如下:
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var obj = new MAPIManaged.InstanceManager();
obj.Init();
}
}
}
(2) 上还有一个 Project-Reference。 我通过 Right-Clicking 项目 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
您永远不应静态 link 任何 MAPI 函数 - 您必须首先找到正确的 MAPI dll 并使用 LoadLibrary / GetProcAddress。
查看 MFCMAPI source code 示例,了解如何完成此操作。
扩展 Dmitry 的回答 - mapi32.lib 的唯一版本存在错误(缺少导出、错误的参数数量和类型等)并且十多年来不受 Microsoft 支持。 MSDN 文章 Link to MAPI functions 对此进行了深入讨论,并提供了许多 linking 到 MAPI 的选项,所有这些都归结为: 1 - 找到要加载的正确 MAPI DLL,这很重要,涉及调用 FGetComponentPath 以找到 MAPI 的正确实现。实际上,您可以通过 linking 到系统 mapi32.dll(它本身是一个存根)来稍微简化此步骤,但是您将错过 Outlook 的 MAPI 提供的导出,这些导出未在系统中公开存根。 2 - 找到后,使用 LoadLibrary 和 GetProcAddress link 导出。
这篇文章也links给微软推荐的MAPIStubLibrary,其中封装了上述逻辑。最好使用此存根库而不是手动滚动位置和 linking 逻辑。
免责声明:我是一名 Microsoft 员工,是 MFCMAPI 的作者,并且是 MAPI 存根库以及 Outlook 开发团队的合著者。