C# Get running Outlook instance in VSTO add-in - c#

I am trying to get an Outlook Application object in my add-in for Excel.
If there's a running Outlook instance, it should get that, if there isn't any, it should create one, using the Outlook object model.
This is the code I have right now:
public static Outlook.Application GetApplicationObject()
{
Outlook.Application application = null;
if (Process.GetProcessesByName("OUTLOOK").Count() > 0)
{
application = Marshal.GetActiveObject("Outlook.Application") as Outlook.Application;
}
else
{
application = new Outlook.Application();
}
return application;
}
My problem: it finds Outlook processes, but can't get them, throwing the following error message:
Operation unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))
I tried debugging it step by step, and monitored the task manager. I could see that I have an Outlook instance, but it's only an icon in the right side of the taskbar. Does this mean, that the instance is not fully loaded yet, and it can't be accessed, to get the Application object from it?
I ended up modifying my code, and separating the if-else into 2 try-catches, with their own returns, but I still think that the code above should be usable.

Outlook is a singleton, so new Outlook.Application() will always work - if it is already running, you will get that running object.
Make sure both apps (Excel and Outlook) are running in the same security context. Is either app running with elevated privileges (Run As Administrator)?

Related

Why is Outlook crashing when using Office interop?

I am attempting to utilize Office interop with C#, but I'm having some difficulties. Executing a test like the one I included below seems to work insofar as it launches Outlook and seems to connect with it. The issue is that if I then try to open the Outlook window (it starts hidden in the tray) I get an error message from Outlook saying The application was unable to start correctly (0xc0000142). I do not get this error if Outlook was already running before I started my application. Am I doing something incorrectly or is something broken?
using System;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace OutlookInteropTest1
{
class Program
{
static void Main(string[] args)
{
var app = new Outlook.Application();
Console.ReadKey();
}
}
}
Visual Studio Community 2017 Version 15.2
Office 360 - Outlook Version 1804 Build 9226.2156
Windows 10 Build 17115.1
EDIT: Tested this on Windows 7 and could not reproduce crash. I know that I had this working in Windows 10 at some point. I reinstalled my OS and it still crashes. I'm chocking this up to the typical Microsoft user experience unless anyone has any ideas on how to fix it.
Outlook is a singleton, so creating a new object will return the existing object if Outlook is already running.
In your case you also need to provide namespace to it
olApp = new Outlook.Application();
Outlook.Namespace ns = olApp.GetNamespace("MAPI");
ns.Logon();
I know this is old, but I was having the same issue and perhaps it will help someone in the future:
As IAmRajshah mentioned, only one istance of outlook can run, so, if Outlook is open your code olApp = new Outlook.Application();will crash, you need to "connect" to the active instance of outlook with somenthing like this Oulook.Application olApp = Marshal.GetActiveObject("Outlook.Application") as Outlook.Application; The link below has a good example of this:
Get and sign in to an instance of Outlook

Problems accessing Outlook from c# Application

I'm writing a console application, which checks the contents of an outlook mailbox, in order to read the contents of specific emails into a database.
This application works fine within Visual studio, whether or not Outlook is open.
If I build the application and run it from the exe it only works when Outlook is open, which isn't really a problem.
However, I need to run it from a scheduled task as it has to run every few minutes. This will not work at all.
I'm using the following code:
System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName("OUTLOOK");
int collCount = processes.Length;
if (collCount != 0)
{
OutlookApp = Marshal.GetActiveObject("Outlook.Application") as Application;
}
else
{
OutlookApp = new Application();
}
The error message I'm getting is:
System.Runtime.InteropServices.COMException (0x800401E3): Operation
unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))
at System.Runtime.InteropServices.Marshal.GetActiveObject(Guid&
rclsid, IntPtr reserved, Object& ppunk) at
System.Runtime.InteropServices.Marshal.GetActiveObject(String progID)
at ImportCruiseEmails.Program.Main()
On the line :
Marshal.GetActiveObject("Outlook.Application") as Application;
Both Outlook and the console application are running under my user account, which has administrator permissions. I've been pulling my hair out with this all afternoon. Can anybody please shed any light on it? Cheers!
Even through the user accounts are the same, security contexts are different since the scheduler runs as a service. And no Office app can be used in a service.
Your options are
In case of an Exchange Server, use EWS to access the mailbox.
Extended MAPI (C++ or Delphi only)
Redemption (I am its author, any language) - it wraps Extended MAPI and its RDO family of objects can be used from a service.

Error while using SHDocVw.InternetExplorer in C#2.0

all,
I have code in C# 2.0 like this:
SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindowsClass();
foreach (SHDocVw.InternetExplorer ie in shellWindows)
{
//.........
}
It is console exe for a 64bit Windows Server 2008 R2 Standard with sp1, IE9.
Basically it launches IE and download a file, then process that file.
When I run it manually, such as double click or from Command console, it works just fine. However, when I set up a Scheduled Task through Task Scheduler, it throws the error at the first line above:
Retrieving the COM class factory for component with CLSID {9BA05972-F6A8-11CF-A442-00A0C90A8F39} failed due to the following error: 8000401a.
I think it must be a permission issue,but I couldn't figure out how to fix it. Any ideas?
Thanks.
I suspect this is to do with access to the desktop.
As shdocvw has a UI, it requires permission to get the desktop handle. When it creates a window it must have a parent window and the desktop window handle is king (or Queen).
However, a scheduled task (for any user) cannot get the desktop handle unless the user is already logged-in in the foreground.

How to detect if a user is accessing an outlook process, that I have started?

I have a C# application, in which I access outlook through the Office PIAs in order to parse appointments. In my application, when I create my outlook object, a new outlook process is created in the task manager. When I close my application, I also quit the outlook object. This shuts down the outlook process in my task manager.
My problem is, when the user is also interacting with outlook. Specifically, if the user has outlook opened, when my program closes, my program also closes that user's outlook program. Experimenting with opening outlook both manually and with my program, while watching the task manager, it seems that only one instance of outlook can ever be running at the same time, and both the user and my program then accesses that same instance, so when I close outlook from my program, I also shut down the user's program.
Strangely enough, the reverse is not the case. If the user shuts down outlook, while my program runs, his window will disappear, but the outlook process will not shut down, and my program can still continue. It is as if the window is only a client of the outlook process, although there is no separate process for the window. Is there a way for me to see, if my program is the only one using the outlook process, or if there are any "user window clients" open, so I can avoid shutting down outlook, when it is still in use?
I found a solution myself. I turns out that outlook keeps track of how many explorers are open on it. Reaching zero explorers does not cause a shutdown of the process, but it indicates that no user has any normal outlook window open, so the process can be safely shut down. In my project I have a single class which accesses outlook. My solution is to test for zero explorers in the destructor of that class (the following code assumes "using Outlook = Microsoft.Office.Interop.Outlook;"):
~OutlookAccessor()
{
try
{
Outlook.Application app = new Outlook.Application();
if (app.Explorers.Count == 0)
{
((Outlook._Application)app).Quit();
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
}
catch (System.Runtime.InteropServices.COMException)
{
; // nevermind, we're only trying to free the Outlook COM object, and the most probable cause for this exception is that office is not installed.
}
}
Of course, you have to be careful to close all explorers you use in your code, or the solution will not work, e.g.:
private void AccessOutlook(Outlook.MAPIFolder topfolder)
{
Outlook.Explorer explorer = null;
try
{
explorer = topFolder.GetExplorer();
... // do stuff with the explorer
}
finally
{
if (explorer != null)
{
((Outlook._Explorer)explorer).Close();
}
}
}

Office 2007: Programmatically control Out-Of-Office assistant?

Does anybody know how to programmatically enable/disable the actual state of the out-of-office auto-responder in Outlook 2007?
Already searched the object browser in VS 2008 and found the enumeration Microsoft.Office.Interop.Outlook.OlBusyStatus but i didn't find any class or anything else using this.
Any idea is appreciated, thanks and regards
UPDATE: Updated the code below using sample code adapted from this blog post which will work better in a wider variety of Outlook installations (e.g. ones using both Exchange and PST or accessing multiple Exchange mailboxes).
Here's code which worked for me on Outlook 2007, to set the OOF status from an external (to Outlook) EXE:
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.ApplicationClass();
Microsoft.Office.Interop.Outlook.NameSpace ns = app.Session;
foreach (Microsoft.Office.Interop.Outlook.Store store in ns.Stores)
{
if (store.ExchangeStoreType == Microsoft.Office.Interop.Outlook.OlExchangeStoreType.olPrimaryExchangeMailbox)
{
store.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x661D000B", true); // false to turn off OOF
break;
}
}
Make sure you're not running that code as Administrator and outlook as non-Administrator-- otherwise you may get a security-related error on Vista.
Note that it will pop up security dialogs inside Outlook to ensure the user is OK with you accessing the Outlook object model. This is normal when outlook object model is accessed from an external EXE.
If, however, you're accessing the object model from an add-in, the code above isn't fully correct: instead of creating a new Outlook.Application object via the constructor, you you need to get a reference to the trusted Outlook.Application object from inside your add-in, like this:
Microsoft.Office.Interop.Outlook.NameSpace ns = this.Application.Session;
foreach (Microsoft.Office.Interop.Outlook.Store store in ns.Stores)
{
if (store.ExchangeStoreType == Microsoft.Office.Interop.Outlook.OlExchangeStoreType.olPrimaryExchangeMailbox)
{
store.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x661D000B", true); // false to turn off OOF
break;
}
}
BTW, there's a good MSDN article on security for add-ins, which may be useful if you run into security dialogs or errors.

Categories