使用 Marshal.GetActiveObject("Outlook.Application") 时的奇怪行为
Strange behaviour when using Marshal.GetActiveObject("Outlook.Application")
为了启动 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 相同的用户下(参见 here)。
控制台应用程序的输出是:
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))
在我单击控制台 window 或调整它的大小之前,此消息会重复出现。 然后输出更改为
Outlook is running.
这只会在使用 profile 参数启动 outlook 时发生。如果没有配置文件参数,消息 Outlook is running.
在我在 Outlook 配置文件对话框中选择配置文件后立即出现。
任何人都可以解释这种行为的原因吗?
尝试使用 WaitForInputIdle()
强制应用程序的处理等待消息循环返回到空闲状态。当一个带有用户界面的进程正在执行时,它的消息循环在操作系统每次向进程发送 Windows 消息时执行。然后进程returns进入消息循环。当一个进程在消息循环中等待消息时,它被称为空闲状态。此状态很有用,例如,当您的应用程序需要等待启动进程完成创建其主进程 window,然后应用程序才与该 window 通信。如果进程没有消息循环,WaitForInputIdle()
抛出 InvalidOperationException
.
此外,我建议在检查它是否为 运行 之前添加任何延迟。
Process.Start(startInfo);
Thread.Sleep(5000);
另一种可能的解决方案是将 COM 自动化与 Logon 方法结合使用,该方法允许指定配置文件名称:
myNameSpace = Application.GetNamespace("MAPI");
myNameSpace.Logon("LatestProfile", Type.Missing , true, true);
为了启动 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 相同的用户下(参见 here)。
控制台应用程序的输出是:
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))
在我单击控制台 window 或调整它的大小之前,此消息会重复出现。 然后输出更改为
Outlook is running.
这只会在使用 profile 参数启动 outlook 时发生。如果没有配置文件参数,消息 Outlook is running.
在我在 Outlook 配置文件对话框中选择配置文件后立即出现。
任何人都可以解释这种行为的原因吗?
尝试使用 WaitForInputIdle()
强制应用程序的处理等待消息循环返回到空闲状态。当一个带有用户界面的进程正在执行时,它的消息循环在操作系统每次向进程发送 Windows 消息时执行。然后进程returns进入消息循环。当一个进程在消息循环中等待消息时,它被称为空闲状态。此状态很有用,例如,当您的应用程序需要等待启动进程完成创建其主进程 window,然后应用程序才与该 window 通信。如果进程没有消息循环,WaitForInputIdle()
抛出 InvalidOperationException
.
此外,我建议在检查它是否为 运行 之前添加任何延迟。
Process.Start(startInfo);
Thread.Sleep(5000);
另一种可能的解决方案是将 COM 自动化与 Logon 方法结合使用,该方法允许指定配置文件名称:
myNameSpace = Application.GetNamespace("MAPI");
myNameSpace.Logon("LatestProfile", Type.Missing , true, true);