COM Interop & Outlook - Make Outlook Visible?
I'm automating Outlook from a VB.NET program, transferring items into the calendar and contacts at the user's request. It's all working, that isn't the开发者_Go百科 problem; the problem is that automating Outlook like this when it wasn't already open creates a hidden instance. I can perhaps understand how this could be useful, to stop the user closing it down while you're still working on it, but since Outlook appears to force one instance only, if the user tries to inspect the changes made while my program is still hooked into Outlook, nothing happens - the one instance is that hidden instance and the user can't see anything.
In the old days of COM automation I used to be able to make Word or Excel visible, but I seem unable to do that with Outlook. I've tried:
OutlookApp.Visible = True
OutlookApp.Application.Visible = True
OutlookApp.ActiveWindow.Visible = True
OutlookApp.ActiveExplorer.Display()
but none of them work.
It's not critical, but does anyone know if I can get Outlook to show its main window? Bonus points if I can get it to disallow the user to close down the instance, but I'll settle for just showing the window :)
You can show your create mail like this :
mailItem.Display();
It is c# code, but I think, this but be close to your vb.
I normaly test to see if the "Outlook" process is running first, if not then shell up Outlook.exe then attach. This way you should never get a hidden process.
There really is no way to cancel the shut down outlook, you can hook the application quit event to disconnect and dispose in your app though.
I came across this question just now because I had the same challenge. I wasn't entirely happy with the accepted answer since this meant I would have to determine the full path of Outlook.exe
. "Shelling up Outlook.exe
" does not work. Therefore, I looked for and found another solution. But before I present that, let's look at how you can determine the full path of Outlook.exe
if you want to do that.
To determine the full path of Outlook.exe
, you need to fetch the Path
value from the
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\16.0\Outlook\InstallRoot
registry key (assuming you have Office 16, a.k.a. Office 2016 or 2019) and build the full path of Outlook.exe
. On my machine, the Path
value is
C:\Program Files\Microsoft Office\root\Office16
so the full path is
C:\Program Files\Microsoft Office\root\Office16\Outlook.exe
However, you need to take into account that the user might have an older (e.g., Office 15, a.k.a. Office 2013) or newer Office version installed and pick the appropriate registry key. You can also get the Office version by retrieving the default value of the
HKEY_CLASSES_ROOT\Outlook.Application\CurVer
key (e.g., Outlook.Application.16
). From this, you can infer the version number (e.g., 16
) and build the segment of your registry key (e.g., 16.0
). Or you can try to find the key with a subkey Outlook\InstallRoot
having a Path
value. Anyhow, you might see why I wanted to avoid this.
So let's look at an easier solution, noting that I am working with multiple Office applications and, therefore, have the following using directive:
using Outlook = Microsoft.Office.Interop.Outlook;
To make Outlook show its main window if no window is currently visible, I wrote the following utility method:
private static void EnsureOutlookIsVisible(Outlook.Application outlook)
{
object window = null;
NameSpace ns = null;
MAPIFolder folder = null;
try
{
// Check whether Outlook has an active window. If so, Outlook is visible
// and we don't have to do anything.
window = outlook.ActiveWindow();
if (window != null) return;
// No active window is shown, so Outlook is not visible and we need to
// have Outlook display a window.
ns = outlook.GetNamespace("MAPI");
folder = ns.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
folder.Display();
}
finally
{
folder.ReleaseComObject();
ns.ReleaseComObject();
window.ReleaseComObject();
}
}
The above method uses the following extension method to release COM objects:
public static void ReleaseComObject<T>(this T resource) where T : class
{
if (resource != null && Marshal.IsComObject(resource))
{
Marshal.ReleaseComObject(resource);
}
}
With the above methods, to attach to a new or existing Outlook process and make sure Outlook shows its main window, all you need are the following two lines of code:
var outlook = new Outlook.Application();
EnsureOutlookIsVisible(outlook);
精彩评论