【问题标题】:Defeating 'A program is trying to access email' with SendMessage使用 SendMessage 击败“程序正在尝试访问电子邮件”
【发布时间】:2011-12-23 00:09:35
【问题描述】:

我正在用 C# 编写一个应用程序,它使用 Office Outlook Interop(2010;版本 14)通过 MAPI 访问电子邮件数据。

到目前为止,我必须在 Outlook 的“程序正在尝试访问存储在 Outlook 中的电子邮件地址信息”安全弹出窗口中手动反复单击“允许”(屏幕截图位于 http://i.stack.imgur.com/gj8to.png)。

我尝试编写一个自动点击的方法,但没有成功。单击发生,但 Outlook Interop 在下一次读取操作期间引发以下异常:

来自 HRESULT 的异常:0x80004004 (E_ABORT)

以下是使用 SendMessage 单击“允许”按钮的代码摘录:

private const Int32 BM_CLICK = 0x00F5;
private const Int32 GWL_STYLE = -16;
private const Int32 CB_SETCURSEL = 0x14E;
private const Int32 WM_LBUTTONDOWN = 0x201;
private const Int32 WM_LBUTTONUP = 0x202;

private const string dialogClass = "#32770";
private const string dialogTitle = "Microsoft Outlook";
const string tickBoxTitle = @"&Allow access for";
const string tickBoxClass = @"Button";

private const int ThreadSleepTime = 1000;
private const int ThreadUiSleepTime = 20;

IntPtr popupHandle;
IntPtr tickHandle = IntPtr.Zero;
IntPtr comboHandle = IntPtr.Zero;
IntPtr allowHandle = IntPtr.Zero;
while ((popupHandle = FindWindow(dialogClass, dialogTitle)) != IntPtr.Zero)
{
    // Get object handles
    tickHandle = FindWindowEx(popupHandle, tickHandle, tickBoxClass, tickBoxTitle);
    comboHandle = FindWindowEx(popupHandle, tickHandle, null, null);
    allowHandle = FindWindowEx(popupHandle, comboHandle, null, null);

    // Click on tickbox until the combobox is enabled
    while ((GetWindowLong(comboHandle, GWL_STYLE) & 0x8000000) != 0)
    {
        SendMessage(tickHandle, BM_CLICK, new IntPtr(1), IntPtr.Zero);
        System.Threading.Thread.Sleep(ThreadUiSleepTime);
    }

    // Set dropdown box selection index to 3rd row
    SendMessage(comboHandle, CB_SETCURSEL, 3, 0);
    System.Threading.Thread.Sleep(ThreadUiSleepTime);

    // Click Allow button
    //SendMessage(allowHandle, BM_CLICK, new IntPtr(1), IntPtr.Zero);

    SendMessage(allowHandle, WM_LBUTTONDOWN, IntPtr.Zero, new IntPtr(MakeLParam(5, 5)));
    System.Threading.Thread.Sleep(ThreadUiSleepTime); 
    SendMessage(allowHandle, WM_LBUTTONUP, IntPtr.Zero, new IntPtr(MakeLParam(5, 5)));
}

为什么 SendMessage 不起作用,我怎样才能使它起作用?

【问题讨论】:

    标签: c# winapi outlook office-interop


    【解决方案1】:

    您应该使用不显示这些警告的 EMAPI。
    Redemption library 提供了一个方便的包装器。

    【讨论】:

      【解决方案2】:

      由于垃圾邮件滥用,不应该有一种方法来覆盖。

      但是,使用另一个线程搜索并按下按钮是可行的。

      请注意,SendMessage 不适用于鼠标按钮。您必须使用可访问性 API 或 WM_COMMAND。

      哦,顺便说一句,不要使用延迟循环来重新发送相同的消息。

      【讨论】:

      • 另请注意,如果机器被锁定、在终端服务等中,这些都不起作用。它必须是某个地方的已登录和可见会话。
      • 一些可访问性 API 在服务会话中工作。众所周知,WM_COMMAND 会这样做。
      • @Joshua,我的方法(上面)确实在单独的线程中运行。从长远来看,我将尝试使用 Redemption 重新编写应用程序,但现在我真的需要让它工作。目前,我的代码勾选了复选框并选择了 10 分钟的超时,但即使它似乎点击了允许我的应用程序在此后立即崩溃,就像点击了拒绝一样。您能按照建议帮助我使用 WM_COMMAND 实现该功能吗?将不胜感激!
      • 您需要像 BUTTON 对象一样将 WM_COMMAND 发送到父窗口。阅读 MSDN 上的文档。
      猜你喜欢
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      • 2014-08-22
      • 2021-12-31
      • 2020-11-18
      • 1970-01-01
      • 2021-06-24
      • 1970-01-01
      相关资源
      最近更新 更多