Я работаю над проектом, в котором мне нужно автоматизировать некоторые рабочие процессы в Excel, и я столкнулся с довольно неприятным препятствием. В проекте я использую Visual Studio Tools For Office для создания надстройки уровня документа. Пользователь использует элемент управления ленты, который является частью этого проекта, для автоматизации копирования рабочих листов из рабочих книг, внешних по отношению к проекту. Внешние книги загружаются из больших двоичных объектов SQL и записываются на диск. Код надстройки открывает каждую книгу, копирует лист в книгу надстройки, а затем закрывает эту внешнюю книгу. Как правило, первая книга работает нормально, но открытие следующей книги вызовет исключение AccessViolationException.
public void AddSheetFromTempFile(string tempfilePath)
{
Sheets sheets = null;
Excel.Workbook workbook = null;
Excel.Workbooks books = null;
try
{
books = this.Application.Workbooks;
//Throws AccessViolationException
workbook = books.Open(tempfilePath, 0, true, 5,
String.Empty, String.Empty, true, XlPlatform.xlWindows,
String.Empty, true, false, 0, true, true, false);
sheets = workbook.Worksheets;
sheets.Copy(After: this.GetLastWorksheet());
workbook.Close(SaveChanges: false);
}
finally
{
if (sheets != null)
{
Marshal.FinalReleaseComObject(sheets);
}
if (workbook != null)
{
Marshal.FinalReleaseComObject(workbook);
}
if (books != null)
{
Marshal.FinalReleaseComObject(books);
}
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
//extension method for getting last worksheet
public static Microsoft.Office.Interop.Excel.Worksheet
GetLastWorksheet(this Microsoft.Office.Tools.Excel.WorkbookBase workbook)
{
int veryHiddenSheets = 0;
foreach(Worksheet sheet in workbook.Worksheets)
{
if(sheet.Visible == XlSheetVisibility.xlSheetVeryHidden)
{
veryHiddenSheets++;
}
}
int lastIndex = workbook.Worksheets.Count - veryHiddenSheets;
return workbook.Worksheets[lastIndex];
}
Поэтому я сузил проблему до набора повторяющихся шагов. Эти проблемы, по-видимому, возникают из-за случаев, когда вы добавляете несколько листов N в книгу, затем удаляете их и снова добавляете лист. Я включил встроенную отладку, предложенную здесь http://social.msdn.microsoft.com/forums/en-US/vsto/thread/48cd3e88-d3a6-4943-b272-6d7ea81e11e3. Я вижу следующий стек вызовов, когда исключение выше.
ntdll.dll!_ZwWaitForSingleObject@12() + 0x15 bytes
ntdll.dll!_ZwWaitForSingleObject@12() + 0x15 bytes
kernel32.dll!_WaitForSingleObjectExImplementation@12() + 0x43 bytes
[External Code]
First-chance exception at 0x2ff2489e in Excel.exe: 0xC0000005: Access violation reading location 0x00000000.
A first chance exception of type 'System.AccessViolationException' occurred in PublicCompModel.DLL
An exception of type 'System.AccessViolationException' occurred in PublicCompModel.DLL but was not handled in user code
Не уверен, что я неправильно использую COM-объект, но мне определенно кажется странным, что я могу воспроизвести это, удалив все листы, и что это локально для Excel.