我有一个 Winforms 应用程序,可以使用 Excel Interop 生成 Excel 电子表格。
当我尝试以这种方式保存工作表时:
_xlBook.SaveAs(filename, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
...它会失败,告诉我,“System.Runtime.InteropServices.InvalidComObjectException 未处理 HResult=-2146233049 Message=已与其底层 RCW 分离的 COM 对象无法使用。"
但这并没有多大意义——我并没有对线程之类的东西做任何花哨的事情;这是一个非常简单的普通实用程序。代码中唯一引用 _xlBook 的其他位置是:
1)
private Excel.Workbook _xlBook;
2)
_xlBook = _xlApp.Workbooks.Add(Type.Missing);
3)
_xlSheets = _xlBook.Worksheets;
_xlSheet = (Excel.Worksheet)_xlSheets.Item[1];
4)
_xlBook.Close(false);
Marshal.ReleaseComObject(_xlBook);
最后一部分,即 _xlBook 被释放的地方,是从表单的 Deactivate 事件中调用的,该事件是:
private void FormMain_Deactivate(object sender, EventArgs e)
{
DeinitializeExcelObjects();
}
问题是(我在引用 _xlBook 的所有位置放置断点后发现),FormMain_Deactivate() 在调用 _xlBook.SaveAs() 之前被调用,而 _xlBook.SaveAs() 被调用时单击“运行”按钮。
一旦我在 FormMain_Deactivate() 中注释掉对 DeinitializeExcelObjects() 的调用,并在调用 _xlBook.SaveAs() 之后立即调用它,它就可以正常工作 - 文件被创建并保存,没有任何错误消息。
那么为什么在表单关闭之前调用 FormDeactivate 呢?如果这在某种程度上是“按照设计的”,那么该事件的命名就严重错误了。
最佳答案
您将代码放在了错误的位置。 :-) 看来您误解了激活和停用的含义(至少就 Windows 而言)。
只要激活不同的窗口,就会发生停用,显然,当您的表单被销毁时,另一个窗口必须变为事件状态,即使该窗口是 Windows 桌面。 FormDeactivate 可以被多次调用(例如当用户切换到不同的应用程序,甚至是您自己的应用程序中的不同窗口时)。值得注意的是,这也适用于激活; FormActivate 也可以多次触发。
如果您希望代码在关闭表单时运行,请将其放入 FormClose 事件处理程序中。
关于c# - 为什么在关闭表单之前调用 FormDeactivate?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38086915/