使用Marshal.GetActiveObject("Outlook.Application")时的奇怪行为。

问题描述 投票:0回答:1

为了启动outlook并等待它通过Interop可用,我写了下面的控制台应用程序。

static Outlook.Application outlook;
static void Main(string[] args)
{
    Console.WriteLine("Enter Profile:");
    var profile = Console.ReadLine();

    var process = Process.GetProcessesByName("Outlook").FirstOrDefault();
    if (process == null)
    {
        ProcessStartInfo startInfo = new ProcessStartInfo("outlook.exe", $"/profile \"{profile}\""); // MK_E_UNAVAILABLE appears until I click in the console window
        // ProcessStartInfo startInfo = new ProcessStartInfo("outlook.exe"); // Works as expected
        process = Process.Start(startInfo);
    }

    while (outlook == null && !process.HasExited)
    {
        try
        {
            outlook = (Outlook.Application)Marshal.GetActiveObject("Outlook.Application");
            break;
        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.Message);
            outlook = null;
        }
        process.Refresh();
        Thread.Sleep(500);
    }

    if (outlook != null)
        Console.WriteLine($"Outlook is running.");

    Console.ReadKey();
}

我在任务管理器中验证了控制台应用程序与Outlook在同一个用户下运行(见 此处).

控制台应用程序的输出是。

Vorgang nicht verfügbar. (Ausnahme von HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))
Vorgang nicht verfügbar. (Ausnahme von HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))
Vorgang nicht verfügbar. (Ausnahme von HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))

这条信息会重复出现,直到我点击控制台窗口或调整其大小。 然后输出变为

Outlook is running.

这只发生在启动outlook的时候。概况 参数。如果没有配置文件参数,则消息 Outlook is running. 当我在Outlook配置文件对话框中选择了该配置文件后,就直接出现了。

谁能解释一下这种行为的原因是什么?

c# outlook office-interop
1个回答
1
投票

尝试使用 WaitForInputIdle() 来强制应用程序的处理等待到消息循环返回到空闲状态。当一个带有用户界面的进程正在执行时,每当操作系统向该进程发送Windows消息时,它的消息循环都会执行。进程就会返回到消息循环。当一个进程在消息循环内部等待消息时,就被称为处于空闲状态。例如,当你的应用程序需要等待一个启动的进程完成创建它的主窗口,然后再与该窗口进行通信时,这种状态就很有用。如果一个进程没有消息循环。WaitForInputIdle() 抛出 InvalidOperationException.

另外,我建议在检查是否运行之前加入任何延迟。

Process.Start(startInfo);
Thread.Sleep(5000);

另一个可能的解决方案是使用COM自动化与 登录 方法,允许指定配置文件名称。

myNameSpace = Application.GetNamespace("MAPI"); 
myNameSpace.Logon("LatestProfile", Type.Missing , true, true); 
© www.soinside.com 2019 - 2024. All rights reserved.