0

VC++ 2008,CLR Console App,win7 x64下开发。

我正在使用 .net 和 MS Office v.12 PIA 来做一些 Excel 自动化,效果很好。但现在,我开始了代码的下一部分,其中涉及一些简单的电子邮件事务,所以我试图让 MAPI 在我的代码中工作。基本上,它读取适当的注册表项以获取 OLMAPI32.DLL 文件的完整路径,然后尝试从该 dll 中加载库/GetProcAddress。

这是一个片段:


using namespace System;
using namespace Microsoft::Office::Interop;
using namespace Microsoft::Win32;

int main(array<System::String ^> ^args)
{
    RegistryKey^ subK = Registry::LocalMachine->OpenSubKey("SOFTWARE\\Clients\\Mail\\Microsoft Outlook");
    String^ mailDll = safe_cast<String^>(subK->GetValue("DLLPathEx"));
    CStringW cStrMailDll = mailDll; //Just to put mailDll in a format that LoadLibrary() can read.

    LPMAPIINITIALIZE mapiInit = NULL;

    HMODULE mapiLib = LoadLibrary(cStrMailDll); // This Returns NULL
    if(mapiLib == NULL)
    {
        printf("\nError: %d\n", GetLastError()); // System Error 193 - ERROR_BAD_EXE_FORMAT
        return 1;
    }

    ...(more code)
    ...

LoadLibrary 设置系统错误 193:“%1 不是有效的 Win32 应用程序”对我来说并不令人震惊。在做了一些研究之后,我想我需要做的就是强制 x86 编译。所以我转到配置管理器,在活动解决方案平台下,我唯一的选择是 Win32、新建和编辑。所以我点击New,在“Type or select the new platform”下输入“x86”,然后点击“Copy settings from”选择“Any CPU”或合适的,但我唯一的选择是Win32,而且!我想可能是因为我已经瞄准了 .net,所以为了测试这个理论,我开始了一个新项目,这次是作为 Win32 控制台应用程序。即使在那种类型的项目下,我唯一的选择是Win32。我听说的 x86、x64、Any CPU 和 Itanium 在我的 VS2008 中不存在!

所以我在这里不知所措。如何强制 VS 将我的 exe 编译为 x86,以便我可以使用 mapi 接口?或者是否有我可以使用的 64 位版本的 OLMAPI32.DLL?如果没有 64 位库,并且当我尝试为 x86 设置环境时,VS 给了我最重要的提示,我该怎么让 MAPI 在我的代码中工作?我简直不敢相信我的 64 位环境会自动取消我使用 MAPI 的资格。

谢谢

4

4 回答 4

1

我相信 Win32 在 Visual Studio C++ 中是 x86

于 2011-02-08T06:24:43.020 回答
1

您可以通过 usihg corflags强制 32 位 CLR 。例如CorFlags.exe /32bit+ file.exe

于 2011-02-08T06:31:14.337 回答
0

有一个 64 位版本的 MAPI 与 64 位版本的 MS Outlook 一起提供。这篇 MSDN 文章详细描述了它。

于 2011-02-08T06:27:10.883 回答
0

所以,为了启发那些帮助过我的人,以及任何可能有类似问题并发生在这个线程上的人,这就是我最终要做的......

我放弃了纯 MAPI 路线,决定转而使用 Outlook PIA。所以现在我的代码如下所示:

#define nul Reflection::Missing::Value
#include "stdafx.h"
using namespace System;
using namespace Microsoft::Office::Interop;

int main(array<System::String ^> ^args)
{
    // Create the outlook object
    Outlook::Application^ olApp = gcnew Outlook::Application();

    // Get an instance of the MAPI namespace via the outlook object
    Outlook::NameSpace^ olNs = olApp->GetNamespace("MAPI");

    // Log this instance into the MAPI interface
    // Note that this will cause the user to be prompted for which profile
    // to use. At least, it prompts me, and I only have one profile anyway. Whatever.
    // Change the first argument to the name of the profile you want it to use (String)
    // to bypass this prompt. I personally have mine set to "Outlook".
    olNs->Logon(nul, nul, true, true);

    // Get my Inbox
    Outlook::Folder^ defFolder = safe_cast<Outlook::Folder^>(olNs->GetDefaultFolder(Outlook::OlDefaultFolders::olFolderInbox));

    // Get all of the items in the folder (messages, meeting notices, etc.)
    Outlook::Items^ fItems = defFolder->Items;

    // Sort them according to when they were received, descending order (most recent first)
    fItems->Sort("[ReceivedTime]", true);

    // Show me the folder name, and how many items are in it
    printf("\n%s: %d\n", defFolder->Name, fItems->Count);

    // Make an array of _MailItems to hold the messages.
    // Note that this is a _MailItem array, so it will only hold email messages.
    // Other item types (in my case, meeting notices) cannot be added to this array.
    array<Outlook::_MailItem^>^ mail = gcnew array<Outlook::_MailItem^>(fItems->Count);

    int itemNum = 1;
    int offset = 0;

    // If there's anything in my Inbox, do the following...
    if(fItems->Count)
    {
        // Try to grab the first email with "fItems->GetFirst()", and increment itemNum.
        try
        {
            mail[itemNum++] = safe_cast<Outlook::_MailItem^>(fItems->GetFirst());
        }
        // If it threw an exception, it's probably because the item isn't a _MailItem type.
        // Since nothing got assigned to mail[1], reset itemNum to 1
        catch(Exception^ eResult)
        {
            itemNum = 1;
        }

        // Ok, now use "fItems->GetNext()" to grab the rest of the messages
        for(; itemNum <= (fItems->Count-offset); itemNum++)
        {
            try
            {
                mail[itemNum] = safe_cast<Outlook::_MailItem^>(fItems->GetNext());
            }
            // If it puked, then nothing got assigned to mail[itemNum]. On the next iteration of
            // this for-loop, itemNum will be incremented, which means that *this* particular index
            // of the mail array would be left empty. To prevent this, decrement itemNum.
            // Also, if itemNum ever gets decremented, then that will ultimately cause this loop
            // to iterate more times than fItems->Count, causing an out-of-bounds error. To prevent
            // that, increment "offset" each time you decrement "itemNum" to compensate for the
            // offset.
            catch(Exception^ eResult)
            {
                itemNum--;
                offset++;
            }
        }

        // Show me the money!
        for(int i=1; i <= (fItems->Count-offset); i++)
            printf("%d - %s\n", i, mail[i]->Subject);
    }

    olNs->Logoff();
    return 0;
}

现在我知道如何进入,我可以继续完成我的项目了!谢谢各位的帮助!

干杯! d

于 2011-02-10T16:26:38.977 回答