Как отменить регистрацию объектов COM Excel Interop и правильно закрыть фоновый процесс Excel? - PullRequest
0 голосов
/ 24 апреля 2020

Как и другие, я борюсь с операцией приложения Excel в C#, в которой я не могу должным образом закрыть фоновый процесс Excel, несмотря на попытку отменить регистрацию всех объектов COM. В моем приложении я извлекаю данные имени тега для историка данных. Приложение ссылается на электронную таблицу Excel для получения имен тегов, используемых в контроллере, который я обрабатываю в нисходящем направлении.

Рассматриваемый метод выглядит следующим образом:

    public class StoreGroupTags
    {
        public static TagGroup StoreDCSTags()
        {
            // Diagnostic timer
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            Console.WriteLine("Storing DCS Tags...");            
            TagGroup Tags = new TagGroup();
            XlObjHandler xlObj = new XlObjHandler();

            try
            {
                Excel.Application xlApp = xlObj.Add(new Excel.Application());
                Excel.Workbooks xlWorkbooks = xlObj.Add(xlApp.Workbooks);
                Excel.Workbook xlWorkbook = xlObj.Add(xlWorkbooks.Open(@"C:\Temp\Master File.xlsx"));
                Excel.Sheets xlWorkSheets = xlObj.Add(xlWorkbook.Sheets);
                Excel.Worksheet xlWorkSheet = xlObj.Add(xlWorkSheets[1]);
                Excel.Range xlRange = xlObj.Add(xlWorkSheet.Cells);

                int colCount = 119; // Column(Indirect((REF)) in excel to get this value

                for (int i = 1; i < colCount + 1; i++)
                {
                    string tagName = xlObj.Add(xlRange.Cells[4, i]).Value.ToString();
                    Tag readData = new Tag($"{tagName}");
                    readData = CheckTagsForStrings(readData);
                    Tags.AddTag(readData);
                }

                xlWorkbook.Close();
                xlWorkbooks.Close();
                xlApp.Quit();
            }
            catch (Exception exception)
            {
                Console.WriteLine("Exception thrown during StoreDCsTags(): " + exception);
            }
            finally
            {
                xlObj.Unregister();
                // Clean up of anything else...
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }

            stopwatch.Stop();
            Console.WriteLine("StoreDCSTags() took: " + stopwatch.ElapsedMilliseconds + "ms");
            return Tags;
        }

Вы можете заметить, что Я "регистрирую" каждый объект Excel в оболочке. Я упомянул метод, представленный: { ссылка }, который был очень полезен для отслеживания того, что я называю, и того, что вынуждено отменить регистрацию с помощью маршала. Используя это (и до того, как я попробовал это, без использования оболочки), я смог определить, что for l oop предотвращает закрытие приложения в фоновом режиме. А именно, если я закомментирую для l oop, приложение успешно закроется. Поэтому я считаю, что проблема изолирована от ссылки xlRange.Cells[4,i].Value. Внутри Excel больше нет вызовов для этого для l oop, за исключением xlRange.Cells.

Я не уверен, но пока могу обернуть каждый объект xlRange.Cells[4,i] и сделать попытку закрытия оболочки это, я не могу сказать, если .Value ТАКЖЕ создает СО-объект (хотя тип - Dynami c, пока я не добавлю .ToString ()), который препятствует закрытию приложения. Я читал, что двойные точки - нет-нет в вызовах Interop, но будет ли это квалифицироваться как ситуация с двумя точками? При попытке деформации xlRange.Cells[4,i].Value я получаю недопустимую ошибку аргумента из оболочки (что имеет смысл, поскольку это не тип "Excel.Application / Workbooks / Workbook / et c"). Кто-нибудь может уточнить, являются ли типы .Value dynamici c на самом деле объектами COM? Может ли кто-нибудь пролить свет на то, какие COM-объекты все еще могут быть «открыты» в этом классе и, возможно, как успешно захватить и закрыть их?

Большое спасибо!

...