Исключение из HRESULT: 0x800401E3 (MK_E_UNAVAILABLE) Обходные пути

Из следующего вызова

Marshal.GetActiveObject("Excel.Application")

Я получаю

Операция недоступна (Исключение из HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))

Я считаю, что эта ошибка возникает, когда пользовательские разрешения между моим приложением и excel не совпадают.

Я хочу знать, есть ли способ обхода доступа к открытому excel-приложению независимо от того, как excel открывается, я могу открыть программу, к которой я хочу получить доступ, от администратора.

Также я хотел бы знать, как я могу определить, какие процессы разрешений были открыты? Я использовал ProcessExplorer для просмотра UserProfile (который был одинаковым в обоих приложениях) и Owner (который также был тем же BUILTIN\Administrators)

Фон У меня есть программа, которая запускает разные тесты, вызывая NUnit-console-x86. Приложение, которое тестируется, открывает форму excel, это форма, из которой я хочу прочитать данные. И когда я запускаю свою программу как администратор, или нет, я получаю эти ошибки, я также попытался добавить в Process.StartInfo.Verb = "runas"; к моей программе, которая запускает NUnit, но я все еще получаю эти ошибки

Появляется установка visual studio устраняет проблему, хотя я не хочу устанавливать визуальную студию на каждом компьютере. Может ли кто-нибудь объяснить это мне?

Ответ 1

Глядя на Информация о поддержке Microsoft, 0x800401e3 создается, когда excel (или офис вообще) не активен или работает в Running Таблица объектов. Перед тем, как вы позвоните, вы должны иметь копию Excel. Его либо вы еще не открыли Excel в коде, либо еще не зарегистрировались. Это может быть проблема?

Ответ 2

Добавить ссылку только на "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;
}

Это сработало для меня.

Преимущество: не нужно копировать файл Microsoft.Office.Interop.Excel.dll в установленную папку. Поскольку MS Excel установлен, он будет взят из GAC.

Я тоже использовал Office.dll, но не уверен, действительно ли это необходимо.

Ответ 3

Это проблема несовпадения преобладает между Visual Studio и Excel. Документы Microsoft не говорят этого, но это определенно так. Более серьезная проблема заключается в том, что исключение иногда генерируется, а иногда и не в старых версиях Excel, которые не знают административных преимуществ, то есть в версии 2007.

Когда это происходит, вы должны соответствовать привилегиям как администратор-администратор или нет-нет. Даже Excel без преобладания и администратор Visual Studio могут не работать.

Ответ 4

Чтобы расширить то, что говорит @DylanCorriveau, я обнаружил, что вам нужно использовать один из следующих способов, чтобы избежать этой проблемы.

Способ 1

Я обнаружил, что в некоторых случаях (Excel 2010) запуск Excel первым решает эту проблему. Вам нужно будет скорректировать путь и ждать, чтобы соответствовать вашим потребностям и версии.

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

Способ 2

Другой подход, который я использовал в прошлом, вызывает Excel по-другому:

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

Способ 3

Наконец, в своем приложении (как для Excel 2010, так и для 2016 года) я использовал небольшой обходной путь:

[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");

Если вы запускаете этот код в Excel 2016 во время сеанса RDP, он может быть очень требователен, я обнаружил, что вам нужно настроить RDP, чтобы игнорировать его свернутое состояние. Я нашел эту статью весьма полезной.