.NET <-> late binding <-> Excel, непонятки
От: Alexey.Velichko  
Дата: 06.07.10 14:42
Оценка:
Всем доброго дня!
Имеется .xls-документ, данные в котором нужно периодически обновлять, для этого использую позднее связывание. Код выглядит примерно следующим образом (упрощенный, но багу воспроизвести позволяет):

public void BugTest()
        {
            object application = null;
            object workbooks = null;
            object workbook = null;
            object worksheets = null;
            object sheet1 = null;

            Type excel = Type.GetTypeFromProgID("Excel.Application");

            CultureInfo ci = new System.Globalization.CultureInfo("en-US");

            try
            {
                application = Activator.CreateInstance(excel);

                application.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, application, new object[] { true }, ci);

                workbooks = application.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, application, null, ci);

                workbook = workbooks.GetType().InvokeMember("Add", BindingFlags.InvokeMethod, null, workbooks, null, ci);

                worksheets = workbook.GetType().InvokeMember("Worksheets", BindingFlags.GetProperty, null, workbook, null, ci);

                sheet1 = worksheets.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, worksheets, new object[] { 1 }, ci);

                DummyProcess1(sheet1);
                
                application.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, application, null);
            }
            catch (COMException cme)
            {
                MessageBox.Show(cme.Message + Environment.NewLine + cme.Source,"BugTest");
            }
            catch (Exception exx)
            {
                MessageBox.Show(exx.Message,"BugTest");
            }
            finally
            {
                if (sheet1 != null && Marshal.IsComObject(sheet1))
                {
                    Marshal.ReleaseComObject(sheet1);
                    sheet1 = null;
                }

                if (worksheets != null && Marshal.IsComObject(worksheets))
                {
                    Marshal.ReleaseComObject(worksheets);
                    worksheets = null;
                }

                if (workbook != null && Marshal.IsComObject(workbook))
                {
                    Marshal.ReleaseComObject(workbook);
                    workbook = null;
                }

                if (workbooks != null && Marshal.IsComObject(workbooks))
                {
                    Marshal.ReleaseComObject(workbooks);
                    workbooks = null; 
                }

                if (application != null && Marshal.IsComObject(application))
                {
                    Marshal.ReleaseComObject(application);
                    application = null;
                }

            }           
        }

        public void DummyProcess1(object worksheet)
        {
            for (int i = 1; i < 10000; i++)
            {
                object cell = null, cell2 = null;

                try
                {
                    cell = worksheet.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, worksheet, new object[] { "A" + i.ToString() });
                    cell.GetType().InvokeMember("Value", BindingFlags.SetProperty, null, cell, new object[] { "A" + i.ToString() });

                    cell2 = worksheet.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, worksheet, new object[] { "B" + i.ToString() });
                    cell2.GetType().InvokeMember("Value", BindingFlags.SetProperty, null, cell2, new object[] { Guid.NewGuid().ToString() });

                    Thread.Sleep(10);
                }
                catch (COMException cme)
                {
                    MessageBox.Show(cme.Message + Environment.NewLine + cme.Source, "DummyProcess");
                }
                catch (Exception exx)
                {
                    MessageBox.Show(exx.Message,"DummyProcess");
                }
                finally
                {
                    if (cell != null && Marshal.IsComObject(cell))
                    {
                        Marshal.ReleaseComObject(cell);
                        cell = null;
                    }

                    if (cell2 != null && Marshal.IsComObject(cell2))
                    {
                        Marshal.ReleaseComObject(cell2);
                        cell2 = null;
                    }

                }

            }
        }


Т.е. создается новый экземпляр xl, затем создается книга и запускается некий долгий процесс обновления данных.
И вот в чем проблема:


Причем стоит закрыть диалог — и дальнейшие вызовы проходят нормально. Т.е. почему-то после вывода экселем любого диалога, все взаимодействие накрывается тазом, пока диалог не будет закрыт
Есть идеи, как это побороть? Запрещать пользователю открывать другие файлы, пока идет обновление — как-то не айс

Как бы сделать, чтобы любой файл, открываемый в процессе работы этого кода, открывался бы не в "моем" инстансе экселя, а создавался бы новый?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.