Поток прерывался исключение, возникающее при открытии книги в новом процессе взаимодействия Excel

#c# #vsto #excel-interop

Вопрос:

У меня есть надстройка excel com, которая выполняет некоторые операции с книгой excel. Идея заключается в том, что при открытии файла excel по умолчанию в этой книге из vba будет вызвана открытая функция надстройки com (OpenFile). На этом этапе надстройка откроет новый процесс excel и откроет там пользовательскую книгу. Это работает большую часть времени, но иногда в отмеченной строке возникает следующее исключение:

ИНФОРМАЦИЯ , 05:31:12: Сообщение: Поток прерывается. ИНФОРМАЦИЯ , 05:31:12: Внутреннее исключение: ИНФОРМАЦИЯ , 05:31:12: Источник: ИНФОРМАЦИЯ mscorlib , 05:31:12: HResult: -2146233040 ИНФОРМАЦИЯ , 05:31:12: Целевой сайт: Пустое представление для внутренней(Int32, IntPtr) ИНФОРМАЦИИ , 05:31:12: Трассировка стека: в System.Runtime.Взаимодействия.Маршал.ThrowExceptionForHRInternal(код ошибки Int32, идентификатор ошибки IntPtr) в системе.Динамический.Комрантайм-помощники.Проверьте исключение(Int32 hresult, Except amp; except, UInt32 argErr, строковое сообщение) на сайте вызова.Цель(Закрытие , узел вызова , ComObject , строка , логическое значение ) в системе.Динамический.Обновленыелегаты.UpdateAndExecute3[T0,T1,T2,TRet](сайт сайта вызова, T0 arg0, T1 arg1, T2 arg2) в системе.Динамический.Обновленыелегаты.UpdateAndExecuteVoid3[T0,T1,T2](сайт узла вызова, T0 arg0, T1 arg1, T2 arg2) в VbaApi.Файл AddInApi.OpenFile(строковый путь, логическое значение fromVba)

При сбое вновь созданный процесс завершается сбоем и закрывается. Похоже, что он выбрасывается в совершенно случайных местах в функции RealOpen, так что это не какая-то конкретная ошибка в функции. Иногда он вообще не выбрасывается, и книга открывается в новом процессе и функционирует нормально.

Ниже приведен код, создающий исключение:

 public void OpenFile(string path, bool fromVba)
        {
            if (fromVba)
            {
                // if called from vba, create a new application object and make visible
                Excel.Application singleApp = new Excel.Application();

                // show new application
                singleApp.Visible = true;
                     
                // Get process id
                int processId = ExcelFunctions.GetExcelProcessId(singleApp);

                // give new app focus
                ExcelFunctions.BringMainWindowToFront(processId);

                // get ComAddIn in new application instance
                COMAddIn addIn = singleApp.COMAddIns.Item(ExcelFunctions.GetVersion(singleApp.Version));
                
                // connect it
                addIn.Connect = true;
                
                // automation object
                dynamic automationObject = addIn.Object;

                try
                {
                    // call open file in new instance                                        
                    automationObject.OpenFile(path, false); // Exception is thrown here
                }
                catch (Exception e)
                {
                    LoggerFactory.Logger.Debug(e.StackTrace);
                }
                // close original application if no other workbooks open
                ExcelFunctions.CloseSession(application);              
            }
            else
            {
                RealOpen(path);                
            }
        }

        private void RealOpen(string path)
        {
            try
            {
                OnRealOpen?.Invoke(path);
                if (path.StartsWith("Cannot decode:"))
                {
                    string error = "Error during download.";
                    LoggerFactory.Logger.Error(error);
                    AlertUser();
                    return;
                }

                dynamic WinHttpReq = VBAFunctions.CreateObject("Microsoft.XMLHTTP");
                WinHttpReq.Open("GET", path, false);
                WinHttpReq.Send();

                string FileName = WinHttpReq.GetResponseHeader("Content-Disposition");
                if (FileName == null)
                {
                    AlertUser();
                    return;
                }
                FileName = FileName.Substring(10);
                FileName = FileName.Substring(0, FileName.Length - 1);

                // check if file is already open on this machine           
                if (ExcelFunctions.CheckIfWorkbookOpen(FileName))
                    return;

                SavePath = Path.GetTempPath()   FileName;
                byte[] caseTemplateWithoutData = WinHttpReq.ResponseBody;

                if (WinHttpReq.Status == 200)
                {
                    using (var fs = new FileStream(SavePath, FileMode.Create, FileAccess.Write))
                    {
                        fs.Write(caseTemplateWithoutData, 0, caseTemplateWithoutData.Length);
                    }
                    
                    GetMetaData("http://test.com", SavePath);
                }
                else
                {
                    string error = "Cannot open, download file error.";
                    LoggerFactory.Logger.Error(error   " http status: "   WinHttpReq.Status   " ResponseText: "   WinHttpReq.ResponseText);
                    AlertUser();
                    return;
                }
                SaveDisabled?.Invoke();

                // Closing current workbook, and opens case.
                ReOpenExcel?.Invoke(SavePath); // It never reaches this point when it fails

                // Set focus to ribbon tab.       
                ActivateTab();
            }
            catch (Exception ee)
            {
                LoggerFactory.Logger.Error($"RealOpen - Error: { ee.Message }.");
            }
        }
 

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

Комментарии:

1. Перестройте приложение с конфигурацией отладки вместо выпуска, чтобы иметь номера строк в трассировке стека исключений. Определите неудачный вызов, используя номер строки в приведенном выше фрагменте кода (и сообщите нам, какая это была строка).

2. @cly Спасибо за ответ. Это часть моей проблемы. Похоже, я не могу воспроизвести проблему в среде разработки. Только с развернутым приложением. Но строка, которая создает исключение, такова: automationObject. OpenFile(путь, ложь); // Исключение выбрасывается здесь, по крайней мере, именно здесь оно перехватывается, в OpenFile оно всегда находится в разных местах, например, это проблема со временем или состояние гонки.

3. Взгляните на журнал событий исполняющей машины (eventvwr.exe, журналы системы и приложений). Возможно, там скрыта какая-то связанная с этим информация.

Ответ №1:

Не создавайте новый экземпляр Excel.Application объекта. Также имейте в виду, что COM-объекты имеют сходство с потоками, поэтому, если вы создаете новый COM-объект во вторичном потоке, освободите его (и все его дочерние объекты) с помощью Marshal.ReleaseComObject() .