是什么导致抛出带有消息 "Cannot access 'System.IO.MemoryStream'" 的 COMException?
What causes a COMException with the message "Cannot access 'System.IO.MemoryStream'" to be thrown?
我正在尝试将 DataTable
导出到 Microsoft Excel 2016,我的代码“成功”运行 通过一次。当它执行 运行 并且我尝试打开 Excel 文件时,它告诉我文件格式无效(试图导出到 XLSX
)。这完全是另一个问题,但我将其包括在内以防万一它有任何帮助。
在接下来的每次导出尝试中,代码都会抛出一个 COMException
消息:
Cannot access 'System.IO.MemoryStream'.
堆栈跟踪显示:
at Microsoft.Office.Interop.Excel._Workbook.SaveAs(Object Filename, Object FileFormat, Object Password, Object WriteResPassword, Object ReadOnlyRecommended, Object CreateBackup, XlSaveAsAccessMode AccessMode, Object ConflictResolution, Object AddToMru, Object TextCodepage, Object TextVisualLayout, Object Local)
at MyNamespace.btnExportToExcel_Click(Object sender, EventArgs e) in C:\...\PageName.aspx.cs:line 279
这两个都没有帮助调试进程。我遇到过 Stream
对象在尝试重新打开之前没有关闭的异常情况,这很容易解决,而且这里有大量关于此的问题。
我在 using
语句中创建流,即使发生异常,它也会自动关闭并处理 Stream
。尽管如此,我也尝试手动将 Close
和 Dispose
添加到我的代码的 finally
块中,但仍然会抛出异常。
using (MemoryStream fs = new MemoryStream()) {
try {
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkBook = xlApp.Workbooks.Add(Missing.Value);
var xlSheets = xlWorkBook.Sheets as Excel.Sheets;
var xlNewSheet = (Excel.Worksheet)xlSheets.Add(xlSheets[1], Type.Missing, Type.Missing, Type.Missing);
xlNewSheet.Name = "newsheet";
System.Data.DataTable dt = (System.Data.DataTable)excelGrid.DataSource;
for (int x = 0; x < dt.Rows.Count; x++)
for (int y = 0; y < dt.Columns.Count; y++)
xlNewSheet.Cells[x + 1, y + 1] = dt.Rows[x][y];
xlWorkBook.SaveAs((Stream)fs); // Exception is thrown here.
fs.Position = 0;
string myName = Server.UrlEncode(SearchTitle + ".xlsx");
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=" + myName);
Response.ContentType = "application/vnd.ms-excel";
Response.BinaryWrite(fs.ToArray());
Response.End();
xlWorkBook.Close(true, Missing.Value, Missing.Value);
xlApp.Quit();
} catch (ThreadAbortException) {
// This exception is throw from Response.End by design. Gracefully ignore it.
} catch (Exception ex) {
// Log exception.
throw ex;
} finally {
fs.Close();
fs.Dispose();
}
}
我想也许重新启动我的调试会话会起作用,但这也没有解决问题。
是什么导致 COMException
和消息 Cannot access 'System.IO.MemoryStream'
被抛出?
这里的API是骗人的;它是 Excel 可以做什么的包装器,Excel 是一个可以与文件对话的 COM 服务器。虽然它被描述为取 Stream
,但实际上它要受限得多。它应该与 FileStream
一起工作,但是:它不能与 MemoryStream
一起工作。所以……不要那样做。改为写入临时目录中的文件。
我正在尝试将 DataTable
导出到 Microsoft Excel 2016,我的代码“成功”运行 通过一次。当它执行 运行 并且我尝试打开 Excel 文件时,它告诉我文件格式无效(试图导出到 XLSX
)。这完全是另一个问题,但我将其包括在内以防万一它有任何帮助。
在接下来的每次导出尝试中,代码都会抛出一个 COMException
消息:
Cannot access 'System.IO.MemoryStream'.
堆栈跟踪显示:
at Microsoft.Office.Interop.Excel._Workbook.SaveAs(Object Filename, Object FileFormat, Object Password, Object WriteResPassword, Object ReadOnlyRecommended, Object CreateBackup, XlSaveAsAccessMode AccessMode, Object ConflictResolution, Object AddToMru, Object TextCodepage, Object TextVisualLayout, Object Local)
at MyNamespace.btnExportToExcel_Click(Object sender, EventArgs e) in C:\...\PageName.aspx.cs:line 279
这两个都没有帮助调试进程。我遇到过 Stream
对象在尝试重新打开之前没有关闭的异常情况,这很容易解决,而且这里有大量关于此的问题。
我在 using
语句中创建流,即使发生异常,它也会自动关闭并处理 Stream
。尽管如此,我也尝试手动将 Close
和 Dispose
添加到我的代码的 finally
块中,但仍然会抛出异常。
using (MemoryStream fs = new MemoryStream()) {
try {
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkBook = xlApp.Workbooks.Add(Missing.Value);
var xlSheets = xlWorkBook.Sheets as Excel.Sheets;
var xlNewSheet = (Excel.Worksheet)xlSheets.Add(xlSheets[1], Type.Missing, Type.Missing, Type.Missing);
xlNewSheet.Name = "newsheet";
System.Data.DataTable dt = (System.Data.DataTable)excelGrid.DataSource;
for (int x = 0; x < dt.Rows.Count; x++)
for (int y = 0; y < dt.Columns.Count; y++)
xlNewSheet.Cells[x + 1, y + 1] = dt.Rows[x][y];
xlWorkBook.SaveAs((Stream)fs); // Exception is thrown here.
fs.Position = 0;
string myName = Server.UrlEncode(SearchTitle + ".xlsx");
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=" + myName);
Response.ContentType = "application/vnd.ms-excel";
Response.BinaryWrite(fs.ToArray());
Response.End();
xlWorkBook.Close(true, Missing.Value, Missing.Value);
xlApp.Quit();
} catch (ThreadAbortException) {
// This exception is throw from Response.End by design. Gracefully ignore it.
} catch (Exception ex) {
// Log exception.
throw ex;
} finally {
fs.Close();
fs.Dispose();
}
}
我想也许重新启动我的调试会话会起作用,但这也没有解决问题。
是什么导致 COMException
和消息 Cannot access 'System.IO.MemoryStream'
被抛出?
这里的API是骗人的;它是 Excel 可以做什么的包装器,Excel 是一个可以与文件对话的 COM 服务器。虽然它被描述为取 Stream
,但实际上它要受限得多。它应该与 FileStream
一起工作,但是:它不能与 MemoryStream
一起工作。所以……不要那样做。改为写入临时目录中的文件。