Исключение из 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, чтобы игнорировать его свернутое состояние. Я нашел эту статью весьма полезной.