현재 COM 객체를 사용하는 올바른 방법은 무엇입니까?
이것은 매우 흔한 질문이고 이 질문은 오늘부로 다른 답을 가질 수 있기 때문에 저는 그것을 묻기로 결정했습니다.답이 COM 개체를 사용하는 올바른 방법을 이해하는 데 도움이 되기를 바랍니다.개인적으로, 저는 이 주제에 대해 다른 의견을 듣고 매우 혼란스럽습니다.
지난 5년 동안 저는 COM 객체를 다루는 일을 했었고 규칙은 매우 명확했습니다.
- 코드 행에 단일 마침표를 사용합니다.두 개 이상의 기간을 사용하여 장면 뒤에 명시적으로 해제할 수 없는 임시 개체를 만듭니다.
- 각 항목에 대해 사용하지 않고 대신 for 루프를 사용하고 각 반복에서 각 항목을 해제합니다.
- FinalReleaseComObject를 호출하지 않고 ReleaseComObject를 사용합니다.
- COM 개체를 해제하는 데 GC를 사용하지 마십시오.GC 의도는 주로 디버깅 용도입니다.
- 개체를 생성된 순서와 반대로 해제합니다.
마지막 줄을 읽고 좌절하는 사람도 있을 것입니다. 이것이 Com Object를 올바르게 생성/해제하는 방법에 대해 제가 알고 있던 것입니다. 더 명확하고 논쟁의 여지가 없는 답변을 얻기를 바랍니다.
다음은 이 항목에서 찾은 몇 가지 링크입니다.일부는 ReleaseComObject를 호출해야 한다고 말하고 일부는 그렇지 않습니다.
- Excel COM 개체를 올바르게 릴리스하는 방법(2013년 11월)
- .NET에서 COM 개체를 올바르게 릴리스하는 방법 (2011년 8월)
- 보안관님위험하다고 간주되는 ReleaseComObject (2010년 3월)
- COMObject 릴리스(2004년 4월)
VSTO 시나리오에서는 일반적으로 ReleaseCOMObject를 사용할 필요가 없습니다. ..."
- MSDN - 보안관.ReleaseComObject 메서드(현재 .NET Framework 버전):
"...참조를 포함하는 기본 COM 개체를 해제하려면 이 방법을 사용해야 합니다.."
업데이트:
이 질문은 너무 광범위한 것으로 표시되었습니다.요청하신 대로, 저는 단순화하고 더 간단한 질문을 하도록 하겠습니다.
- COM Object로 작업할 때 ReleaseCom Object가 필요합니까, 아니면 GC를 호출하는 것이 올바른 방법입니까?
- VSTO 접근 방식이 COM 개체를 사용하던 방식을 변화시키나요?
- 제가 작성한 위의 규칙 중 필요한 것과 잘못된 것은 무엇입니까?다른 것은 없습니까?
는 잘합니다.NET/COM 인터op은 잘 설계되었으며 올바르게 작동합니다.특히 .NET Garbage Collector는 COM 참조를 올바르게 추적하며, 남은 런타임 참조가 없을 때 COM 개체를 올바르게 릴리스합니다.COM을 합니다.Marshal.ReleaseComObject(...)
또는Marshal.FinalReleaseComObject(...)
위험하지만 일반적인 안티바이러스입니다.불행하게도, 몇몇 나쁜 조언들은 마이크로소프트에서 나왔습니다.
.NET 코드는 5가지 규칙을 모두 무시한 채 COM과 올바르게 상호 작용할 수 있습니다.런타임에서 더 이상 참조되지 않는 COM 개체의 결정론적 정리를 트리거해야 하는 경우 안전하게 GC를 강제로 적용할 수 있습니다(그리고 완료자가 완료될 때까지 기다릴 수도 있습니다).그렇지 않으면 코드에서 COM 개체를 처리하기 위해 특별한 작업을 수행할 필요가 없습니다.
한 가지 중요한 주의 사항이 있는데, 이는 쓰레기 수집기의 역할에 대해 혼동을 일으켰을 수 있습니다..NET 코드를 디버깅할 때 로컬 변수는 디버거에서 변수를 보는 것을 지원하기 위해 인위적으로 메서드의 끝까지 수명을 연장합니다.즉, 코드만 보고 예상 양식보다 늦게 COM 개체에 대한 참조를 관리할 수 있습니다(따라서 GC가 정리되지 않음).이 문제(디버거에서만 발생)에 대한 좋은 해결 방법은 GC 정리 호출에서 COM 호출 범위를 분할하는 것입니다.
예를 들어, 여기 Excel과 상호 작용하고 제대로 정리되는 C# 코드가 있습니다.콘솔 응용 프로그램에 붙여넣을 수 있습니다(Microsoft에 대한 참조만 추가).사무실. 인터럽트.Excel):
using System;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
namespace TestCsCom
{
class Program
{
static void Main(string[] args)
{
// NOTE: Don't call Excel objects in here...
// Debugger would keep alive until end, preventing GC cleanup
// Call a separate function that talks to Excel
DoTheWork();
// Now let the GC clean up (repeat, until no more)
do
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
while (Marshal.AreComObjectsAvailableForCleanup());
}
static void DoTheWork()
{
Application app = new Application();
Workbook book = app.Workbooks.Add();
Worksheet worksheet = book.Worksheets["Sheet1"];
app.Visible = true;
for (int i = 1; i <= 10; i++) {
worksheet.Cells.Range["A" + i].Value = "Hello";
}
book.Save();
book.Close();
app.Quit();
// NOTE: No calls the Marshal.ReleaseComObject() are ever needed
}
}
}
Excel 프로세스가 제대로 종료되어 모든 COM 개체가 제대로 정리되었음을 나타냅니다.
VSTO는 이러한 문제를 변경하지 않습니다. VSTO는 기본 Office COM 개체 모델을 래핑하고 확장하는 .NET 라이브러리일 뿐입니다.
MSDN 및 StackOverflow에 대한 많은 게시물을 포함하여 이 문제에 대한 많은 잘못된 정보와 혼동이 있습니다.
마침내 제가 더 자세히 살펴보고 올바른 조언을 찾도록 설득한 것은 이 게시물 https://blogs.msdn.microsoft.com/visualstudio/2010/03/01/marshal-releasecomobject-considered-dangerous/ 과 함께 StackOverflow 답변의 디버거 아래에서 유지되는 참조와 관련된 문제를 찾는 것이었습니다.
이 일반 지침의 한 가지 예외는 COM 개체 모델이 인터페이스를 특정 순서로 릴리스해야 하는 경우입니다.여기서 설명하는 GC 접근 방식은 GC에 의해 COM 개체가 해제되는 순서를 제어할 수 없습니다.
저는 이것이 COM 계약에 위반되는지 여부를 나타내는 어떠한 참고 자료도 가지고 있지 않습니다.일반적으로, 저는 COM 계층이 시퀀스에 대한 모든 종속성을 적절하게 관리하기 위해 내부 참조를 사용할 것으로 예상합니다.예를 들어 Excel의 경우 Range 개체가 상위 워크시트 개체에 대한 내부 참조를 유지하므로 개체 모델의 사용자가 명시적으로 둘 다 활성화할 필요가 없습니다.
Office 응용 프로그램에서도 COM 개체가 릴리스되는 순서에 민감한 경우가 있을 수 있습니다.한 가지 경우는 OLE 임베딩이 사용되는 경우인 것 같습니다. https://blogs.msdn.microsoft.com/vsofficedeveloper/2008/04/11/excel-ole-embedding-errors-if-you-have-managed-add-in-sinking-application-events-in-excel-2/ 참조
따라서 개체가 잘못된 순서로 릴리스되면 실패하는 COM 개체 모델을 만들 수 있으며, 이러한 COM 모델과의 상호 작용에는 더 많은 주의가 필요하고 참조에 대한 수동 간섭이 필요할 수 있습니다.
하지만 Office COM 객체 모델과의 일반적인 상호 작용을 위해, 저는 "마샬"이라는 VS 블로그 게시물에 동의합니다.ReleaseComObject – 솔루션으로 위장한 문제"
언급URL : https://stackoverflow.com/questions/37904483/as-of-today-what-is-the-right-way-to-work-with-com-objects
'code' 카테고리의 다른 글
Mongoid / Mongodb 및 내장된 문서 쿼리 (0) | 2023.07.02 |
---|---|
데이터베이스 동의어는 언제 사용해야 합니까? (0) | 2023.07.02 |
둘 이상의 값을 반환하는 함수에서 할당하는 방법은 무엇입니까? (0) | 2023.07.02 |
여러 레코드를 삽입하고 ID 값을 얻는 방법은 무엇입니까? (0) | 2023.07.02 |
v-for(vue.js)에서 데이터를 읽는 방법은 무엇입니까? (0) | 2023.07.02 |