19

From the following call

Marshal.GetActiveObject("Excel.Application")

I get a

Operation unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))

I believe that this error is caused when the user permissions between my application and excel do not match.

I want to know if there is a workaround as to how I can access the opened excel application regardless of how excel is opened, I can open the program that I want to access excell from as an administrator.

Also I would like to know how I can tell what permissions processes were opened with? I have been using ProcessExplorer to look at the UserProfile (which was the same in both applications), and Owner (which was also the same BUILTIN\Administrators)

Background I have a program that run different tests by calling NUnit-console-x86. The application that is being tested opens up an excel form, this is the form that I want to read the data from. And when i run my program as administrator, or not I get these errors, I have also tried adding in Process.StartInfo.Verb = "runas"; to my program that starts up NUnit but I still get these errors

It appears installing visual studio fixes the problem although I do not want to have to install visual studio on every computer. Can anyone explain any of this to me?

Kara
  • 6,115
  • 16
  • 50
  • 57
user1227708
  • 221
  • 1
  • 2
  • 5
  • 2
    I just went through the permission nightmare with Excel and once I set Excel's compatibly mode to run as an administrator as well as the invoking application to be ran as an administrator, everything worked. – MisterIsaak Jan 14 '13 at 05:08
  • I've had this problem so many times, I found that if I encounter the error and switch back and forth between Skype and Excel, it works... – James Heffer Dec 07 '16 at 09:45

4 Answers4

7

Looking at Microsoft Support Information, 0x800401e3 seems to be generated when excel (or office in general) isn't active or running in the Running Object Table. You have to have a copy of excel opened before you call this. Its either you haven't opened excel in code yet, or its not fully registered yet. Could this be the problem?

Dylan Corriveau
  • 2,561
  • 4
  • 29
  • 36
  • 1
    No. It was running. But somehow I was running Visual Studio as a non-administrator. Once I reran it as an administrator, everything started working. – BrainSlugs83 May 05 '16 at 01:59
  • Ahhhh. Yup, that would do it too. Glad you were able to get it working. – Dylan Corriveau May 07 '16 at 15:50
  • 2
    Per the article you linked: "When an Office application starts, it does not immediately register its running objects. This optimizes the application's startup process. Instead of registering at startup, an Office application registers its running objects in the ROT once it loses focus." I've found you need to focus on a different window to accomplish this(just minimizing does work...), somewhat hacky, I wonder if there is a better way :( – David Rogers Apr 12 '19 at 21:33
  • @DavidRogers This worked for me, honestly it should be its own answer. But is also inane as a solution. – Mox Jun 08 '23 at 07:57
2

It's the problem of mismatching previleges between Visual Studio and Excel. Microsoft documents don't say that but it definitely is. The more serious problem is that the exception is sometimes thrown and sometimes not through old versions of Excel which don't know the administrative previliges i.e. version 2007.

When it happens you should match the previleges as administrator-administrator or none-none. Even Excel none-previlege and Visual Studio administrator may not work.

SHIN JaeGuk
  • 494
  • 1
  • 5
  • 14
2

To extend what @DylanCorriveau says, I've found that you'll need to take one the following methods to avoid this issue.

Method 1

I found that in some cases (Excel 2010) starting excel first resolves this issue. You'll need to adjust the path and wait to fit you needs and version.

string pathToTheVersionOfExcel = @"C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE";
System.Diagnostics.Process.Start(pathToTheVersionOfExcel);
Thread.Sleep(5000); //"WaitForInputIdle" waits for way too long, generally it takes 5 seconds to start for me

Method 2

Another approach I've taken in the past is invoking Excel in a different way:

var oExcelApp = new Microsoft.Office.Interop.Excel.Application();

Method 3

Finally in my application (for both excel 2010 and 2016) I've used a bit of a workaround:

[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

//In your method...
string pathToTheVersionOfExcel = @"C:\Program Files (x86)\Microsoft Office\root\Office16\EXCEL.EXE";
Application oExcelApp = null;

Process process = new Process();
process.StartInfo.FileName = pathToTheVersionOfExcel;
process.Start();

Thread.Sleep(5000);

//Opening a closing notepad seems to "register" excel 2016, not needed for excel 2010 though...
Process processNotepad = new Process();
processNotepad.StartInfo.FileName = @"C:\Windows\system32\notepad.exe";
processNotepad.Start();

ShowWindow(process.MainWindowHandle, 2); //Minimize
ShowWindow(process.MainWindowHandle, 3); //Maximize

Thread.Sleep(5000);

processNotepad.CloseMainWindow();

oExcelApp = (_Application)Marshal.GetActiveObject("Excel.Application");

If you running this code in Excel 2016 in a RDP session it can be very picky, I've found that you need to customize RDP to ignore it's minimized state. I found this article quite helpful.

If your trying to invoke excel through some sort of automated build/release platform on a remote server (such as TFS/Azure DevOps), you need to play around with autologin. I haven't got that working yet myself.

David Rogers
  • 2,601
  • 4
  • 39
  • 84
1

Add reference only of "Microsoft.Office.Interop.Excel.dll"

try
{
    //This requires excel app (excel.exe*32) to be running means any excel sheet should be open. If excel not running then it will throw error.
    excelApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
    excelApp.Visible = false;
}
catch
{
    //create new excel instance
    excelApp = new Excel.Application(); 
    excelApp.Visible = false;
}

This worked for me.

Advantage: No need to copy Microsoft.Office.Interop.Excel.dll to your installed folder. Since MS excel is installed it will take from GAC.

I used Office.dll too but not sure if its really required.

David Rogers
  • 2,601
  • 4
  • 39
  • 84
Saikat Chakraborty
  • 271
  • 1
  • 3
  • 11