C#에서 Excel interop 개체를 안전하게 폐기하시겠습니까?
저는 winforms c# visual studio 2008 애플리케이션을 개발하고 있습니다.그 앱은 엑셀 파일과 대화하고 나는 사용하고 있습니다.Microsoft.Office.Interop.Excel;
이를 위해.
오류가 발생했을 때도 물체가 확실히 해제되도록 하려면 어떻게 해야 하는지 알고 싶습니다.
내 코드는 다음과 같습니다.
private void button1_Click(object sender, EventArgs e)
{
string myBigFile="";
OpenFileDialog openFileDialog1 = new OpenFileDialog();
DialogResult result = openFileDialog1.ShowDialog(); // Show the dialog.
if (result == DialogResult.OK) // Test result.
myBigFile=openFileDialog1.FileName;
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Range range;
string str;
int rCnt = 0;
int cCnt = 0;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Open(myBigFile, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", true, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
range = xlWorkSheet.UsedRange;
/*
for (rCnt = 1; rCnt <= range.Rows.Count; rCnt++)
{
for (cCnt = 1; cCnt <= range.Columns.Count; cCnt++)
{
str = (string)(range.Cells[rCnt, cCnt] as Excel.Range).Value2;
MessageBox.Show(str);
}
}
*/
xlWorkSheet..EntireRow.Delete(Excel.XLDirection.xlUp)
xlWorkBook.SaveAs(xlWorkBook.Path + @"\XMLCopy.xls", Excel.XlFileFormat.xlXMLSpreadsheet, Type.Missing, Type.Missing,
false, false, Excel.XlSaveAsAccessMode.xlNoChange,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
xlWorkBook.Close(true, null, null);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
}
private void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
MessageBox.Show("Unable to release the Object " + ex.ToString());
}
finally
{
GC.Collect();
}
}
워크북을 연 후 오류가 발생하더라도 개체를 삭제하려면 어떻게 해야 합니까?
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Range range;
즉, 다음 행이 필요한 경우에도 실행됩니다.
xlWorkBook.Close(true, null, null);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
저도 이것을 시도했고, 그 결과 같은 문제가 발생했다는 것을 알아두세요.
xlWorkBook.Close(false, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
xlApp.Quit();
Marshal.ReleaseComObject(xlWorkSheet);
Marshal.ReleaseComObject(xlWorkBook);
Marshal.ReleaseComObject(xlApp);
xlWorkSheet = null;
xlWorkBook = null;
xlApp = null;
GC.GetTotalMemory(false);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.GetTotalMemory(true);
그리고 저는 이것도 했습니다.
GC.Collect() ;
GC.WaitForPendingFinalizers();
GC.Collect() ;
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(xlWorkSheet);
xlWorkBook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(xlWorkBook);
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
이 시점에서 저는 비주얼 스튜디오 2008에서 엑셀을 닫는 것이 가능하다고 생각하지 않습니다. 버그 같은 것이 틀림없지만, 저는 이것에 대해 상위 20개의 웹사이트를 시도했고 같은 결과를 얻었습니다: 엑셀은 어떤 이유에서인지 두 개의 인스턴스를 열고 있고 쓰레기 수집 등을 할 때입니다.하나의 인스턴스만 닫거나 닫지 않습니다.
파일을 열려고 하면 오류가 있거나 파일이 손상되었다고 표시됩니다.
내가 작업 관리자에게 가서 엑셀 프로세스를 죽이면, 파일은 문제없이 열릴 것입니다.]
비주얼 스튜디오 2008과 엑셀을 닫는 방법이 있습니까? 그렇다면 이에 대한 지침이나 해결책을 제공해 주시겠습니까?
먼저 수정된 내용을 발표하겠습니다.releaseObject
그런 다음 사용할 수 있는 패턴을 제공하겠습니다.
using Marshal = System.Runtime.InteropServices.Marshal;
private void releaseObject(ref object obj) // note ref!
{
// Do not catch an exception from this.
// You may want to remove these guards depending on
// what you think the semantics should be.
if (obj != null && Marshal.IsComObject(obj)) {
Marshal.ReleaseComObject(obj);
}
// Since passed "by ref" this assingment will be useful
// (It was not useful in the original, and neither was the
// GC.Collect.)
obj = null;
}
이제 사용할 패턴:
private void button1_Click(object sender, EventArgs e)
{
// Declare. Assign a value to avoid a compiler error.
Excel.Application xlApp = null;
Excel.Workbook xlWorkBook = null;
Excel.Worksheet xlWorkSheet = null;
try {
// Initialize
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Open(myBigFile, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", true, false, 0, true, 1, 0);
// If the cast fails this like could "leak" a COM RCW
// Since this "should never happen" I wouldn't worry about it.
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
...
} finally {
// Release all COM RCWs.
// The "releaseObject" will just "do nothing" if null is passed,
// so no need to check to find out which need to be released.
// The "finally" is run in all cases, even if there was an exception
// in the "try".
// Note: passing "by ref" so afterwords "xlWorkSheet" will
// evaluate to null. See "releaseObject".
releaseObject(ref xlWorkSheet);
releaseObject(ref xlWorkBook);
// The Quit is done in the finally because we always
// want to quit. It is no different than releasing RCWs.
if (xlApp != null) {
xlApp.Quit();
}
releaseObject(ref xlApp);
}
}
이 간단한 접근 방식은 대부분의 상황에서 확장/내포될 수 있습니다.나는 이 작업을 쉽게 하기 위해 ID를 구현하는 사용자 지정 래퍼 클래스를 사용합니다.
코드에 두 가지 문제가 있는지 확인합니다.
- 프로그램이 닫힐 때 Excel은 실행 중인 프로세스로 남아 있습니다.
- 당신이 엑셀 파일을 열었을 때 당신의 프로그램이 엑셀에서 파일이 손상되었다는 에러를 볼 수 있습니다.
버튼1 클릭 핸들러와 pst를 복사했습니다.releaseObject
편집한 질문의 메서드를 깨끗한 VS2008, C#3.5 Winform 응용 프로그램으로 변환하고 위에 나열한 두 가지 문제를 모두 제거하기 위해 몇 가지 사소한 변경을 가했습니다.
Excel이 메모리에서 언로드되지 않도록 수정하려면 전화하십시오.releaseObject
에서range
생성한 개체입니다.전화를 걸기 전에 이 작업을 수행하십시오.releaseObject(xlWorkSheet);
이러한 모든 참조를 기억하는 것이 COM Interop 프로그래밍을 매우 재미있게 만드는 이유입니다.
하려면 Excel 파일을 하십시오.WorkBook.SaveAs
파라미터를 호출()Excel.XlFileFormat.xlXMLSpreadsheet
)와 함께Type.Missing
.SaveAs
메서드는 기본적으로 이 문제를 올바르게 처리합니다.
질문에 게시한 코드는 현재 발생하고 있는 문제를 디버깅하는 데 도움이 되도록 단순화되어 있습니다.은 다을사합니다야를 해야 합니다.try..finally
블록 pst가 시연합니다.
언급URL : https://stackoverflow.com/questions/9962157/safely-disposing-excel-interop-objects-in-c
'programing' 카테고리의 다른 글
장고 URL 리디렉션 (0) | 2023.09.04 |
---|---|
PHP: 문자열을 각 문자에 대해 배열로 분할 (0) | 2023.09.04 |
도커-공구함 마리애드브 용기 (0) | 2023.09.04 |
판다 데이터 프레임 열에 쉼표를 수천 개의 구분 기호로 삽입하는 방법은 무엇입니까? (0) | 2023.09.04 |
Ajax/jquery 기술로 페이지 내용을 미리 로드할 수 있습니까? (0) | 2023.09.04 |