gpt4 book ai didi

visual-studio-2010 - ThisWorkbook.Application.Workbooks.Open 中的 AccessViolationException

转载 作者:行者123 更新时间:2023-12-04 05:46:07 26 4
gpt4 key购买 nike

我正在做一个项目,我需要在 Excel 中自动化一些工作流程,但我遇到了一个非常讨厌的障碍。在项目中,我使用 Visual Studio Tools For Office 创建文档级加载项。用户使用作为该项目一部分的功能区控件来自动从项目外部的工作簿复制工作表。外部工作簿从 SQL blob 加载并写入磁盘。加载项代码打开每个工作簿,将工作表复制到加载项工作簿中,然后关闭该外部工作簿。通常,第一个工作簿工作正常,但打开后续工作簿将引发 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 工作表,然后删除它们,然后重新添加工作表的情况。我启用了此处建议的 native 调试 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 本地的。

最佳答案

经过大量调试、微软 VSTO 团队的支持票,以及一些漫长的夜晚,我终于找到了答案。问题不是源于我的代码,而是源于工作簿本身。最初,我们将代码编写为一个独立的项目,然后从我们用户的电子表格模型中集成了工作表。关键问题是,当您开始从其他工作簿复制工作表时,您会随同这些工作簿命名引用。我们的用户组为我们提供了一个包含数百个我们以前从未见过的错误引用的文件。

即使您使用 Application 对象抑制警告,这些事件仍会在后台触发。 C# 操作工作簿状态时触发的大量事件导致了 AccessViolationException。

我学到的教训:确保清理工作簿并观察工作簿在没有代码的情况下的行为。由于时间问题,我们被迫在 Microsoft 调试我们的代码时用 VBA 重写解决方案。在我们清理资源之前,VBA 代码运行更稳定,这可能源于它被解释并且根据我的观察在单个线程上运行的事实。

顺便说一句,如果您在文档加载项的上下文中使用 VSTO,则应该小心释放引用。在许多情况下,您可能不需要这样做,因为 Excel 可能会为您清理它。考虑释放 COM 对象 dangerous .

关于visual-studio-2010 - ThisWorkbook.Application.Workbooks.Open 中的 AccessViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10666999/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com