Всем доброго дня!
Имеется .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, затем создается книга и запускается некий долгий процесс обновления данных.
И вот в чем проблема:
— закрываем все открытые экземпляры Excel, если имеются;
— запускаем указанный код;
— в процессе его работы открываем (из проводника, например, двойным кликом) любой эксельный документ, содержащий сслыки на внешние источники данных (или запароленный на редактирование, не суть — главное, чтобы Excel вывел пользователю любой диалог);
— после открытия такого файла, вызов любого метода приводит к возникновению исключений System.Runtime.InteropServices.COMException (0x80010001): Вызов был отклонен. (Исключение из HRESULT: 0x80010001 (RPC_E_CALL_REJECTED)) и System.Reflection.TargetInvocationException: Адресат вызова создал исключение. ---> System.Runtime.InteropServices.COMException: Вызов был отклонен. (Исключение из HRESULT: 0x80010001 (RPC_E_CALL_REJECTED))
Причем стоит закрыть диалог — и дальнейшие вызовы проходят нормально. Т.е. почему-то после вывода экселем любого диалога, все взаимодействие накрывается тазом, пока диалог не будет закрыт
Есть идеи, как это побороть? Запрещать пользователю открывать другие файлы, пока идет обновление — как-то не айс
Как бы сделать, чтобы любой файл, открываемый в процессе работы этого кода, открывался бы не в "моем" инстансе экселя, а создавался бы новый?