In-Process 확장 구현에 대한 지침
In-Process 확장은 이를 트리거하는 모든 프로세스에 로드됩니다. 예를 들어 셸 네임스페이스 확장은 직접 또는 간접적으로 셸 네임스페이스에 액세스하는 모든 프로세스에 로드할 수 있습니다. 셸 네임스페이스는 일반적인 파일 대화 상자 표시, 연결된 애플리케이션을 통한 문서 시작 또는 파일을 나타내는 데 사용되는 아이콘 가져오기와 같은 많은 셸 작업에서 사용됩니다. In-process 확장은 임의의 프로세스에 로드될 수 있으므로 호스트 애플리케이션 또는 다른 In-Process 확장에 부정적인 영향을 주지 않도록 주의해야 합니다.
특정 메모의 한 런타임은 관리 코드 또는 .NET Framework 알려진 CLR(공용 언어 런타임)입니다. Microsoft는 Windows Explorer 또는 Windows Internet Explorer 관리되는 In-Process 확장을 작성하는 것을 권장하며 지원되는 시나리오로 간주하지 않습니다.
이 항목에서는 CLR 이외의 런타임이 In-Process 확장에서 사용하기에 적합한지 여부를 결정할 때 고려해야 할 요인에 대해 설명합니다. 다른 런타임의 예로는 Java, Visual Basic, JavaScript/ECMAScript, Delphi 및 C/C++ 런타임 라이브러리가 있습니다. 또한 이 항목에서는 관리 코드가 In-process 확장에서 지원되지 않는 몇 가지 이유를 제공합니다.
버전 충돌
단일 프로세스 내에서 여러 런타임 버전의 로드를 지원하지 않는 런타임을 통해 버전 충돌이 발생할 수 있습니다. 버전 4.0 이전의 CLR 버전은 이 범주에 속합니다. 런타임의 한 버전을 로드할 때 동일한 런타임의 다른 버전 로드가 제외되는 경우 호스트 애플리케이션 또는 다른 In-Process 확장에서 충돌하는 버전을 사용하는 경우 충돌이 발생할 수 있습니다. 버전이 다른 In-Process 확장과 충돌하는 경우 오류에는 올바른 충돌 확장이 필요하고 오류 모드는 충돌하는 확장이 로드되는 순서에 따라 달라지므로 충돌을 재현하기 어려울 수 있습니다.
버전 4.0 이전의 CLR 버전을 사용하여 작성된 In-Process 확장을 고려합니다. 파일 열기 대화 상자를 사용하는 컴퓨터의 모든 애플리케이션은 잠재적으로 대화 상자의 관리 코드와 해당 수행자 CLR 종속성을 애플리케이션의 프로세스에 로드할 수 있습니다. 먼저 4.0 이전 버전의 CLR을 애플리케이션 프로세스에 로드하는 애플리케이션 또는 확장은 해당 프로세스에서 이후에 사용할 수 있는 CLR 버전을 제한합니다. 열기 대화 상자가 있는 관리되는 애플리케이션이 충돌하는 버전의 CLR을 기반으로 하는 경우 확장이 올바르게 실행되지 않고 애플리케이션에서 오류가 발생할 수 있습니다. 반대로, 확장이 프로세스에서 가장 먼저 로드되고 충돌하는 버전의 관리 코드가 실행하려고 하면(관리되는 애플리케이션 또는 실행 중인 애플리케이션이 요청 시 CLR을 로드하는 경우) 작업이 실패합니다. 사용자에게 애플리케이션의 일부 기능이 임의로 작동을 중지하거나 애플리케이션이 신비하게 충돌하는 것처럼 보입니다.
버전 4.0 이상인 CLR 버전은 서로 공존하고 대부분의 4.0 이전 버전의 CLR(버전 1.0을 제외하고 다른 버전과 공존할 수 없음)과 공존하도록 설계되었기 때문에 일반적으로 버전 관리 문제에 취약하지 않습니다. 그러나 이 항목의 나머지 부분에서 설명한 대로 버전 충돌 이외의 문제가 발생할 수 있습니다.
성능 이슈
성능 문제는 프로세스에 로드될 때 상당한 성능 저하를 초래하는 런타임에서 발생할 수 있습니다. 성능 저하는 메모리 사용량, CPU 사용량, 경과된 시간 또는 주소 공간 소비의 형태일 수 있습니다. CLR, JavaScript/ECMAScript 및 Java는 강력한 런타임으로 알려져 있습니다. In-Process 확장은 여러 프로세스에 로드될 수 있으며 성능에 민감한 순간(예: 사용자에게 표시할 메뉴를 준비할 때)에서 수행되는 경우가 많기 때문에 영향력이 큰 런타임은 전반적인 응답성에 부정적인 영향을 미칠 수 있습니다.
중요한 리소스를 사용하는 영향력이 큰 런타임은 호스트 프로세스 또는 다른 In-Process 확장에서 오류를 일으킬 수 있습니다. 예를 들어 힙에 수백 메가바이트 규모의 주소 공간을 사용하는 강력한 런타임으로 인해 호스트 애플리케이션이 큰 데이터 세트를 로드할 수 없게 될 수 있습니다. 또한 In-Process 확장을 여러 프로세스에 로드할 수 있으므로 단일 확장의 높은 리소스 사용량은 전체 시스템에서 높은 리소스 사용량을 빠르게 곱할 수 있습니다.
런타임이 로드된 상태로 유지되거나 해당 런타임을 사용하는 확장이 언로드된 경우에도 리소스를 계속 사용하는 경우 해당 런타임은 확장에서 사용하기에 적합하지 않습니다.
.NET Framework 관련된 문제
다음 섹션에서는 확장에 관리 코드를 사용할 때 발견된 문제의 예에 대해 설명합니다. 발생할 수 있는 모든 가능한 문제의 전체 목록은 아닙니다. 여기서 설명하는 문제는 확장에서 관리 코드가 지원되지 않는 이유와 다른 런타임의 사용을 평가할 때 고려해야 할 사항입니다.
재입력
예를 들어 MONITOR.Enter, WaitHandle.WaitOne 또는 경합 잠금 문으로 인해 CLR이 STA(단일 스레드 아파트) 스레드를 차단하는 경우 CLR은 대기하는 동안 중첩된 메시지 루프를 입력합니다. 많은 확장 메서드는 메시지 처리를 금지하며, 예측할 수 없고 예기치 않은 재진입으로 인해 비정상적인 동작이 발생하여 재현하고 진단하기 어려울 수 있습니다.
다중 스레드 아파트먼트
CLR은 COM(구성 요소 개체 모델) 개체에 대한 런타임 호출 가능 래퍼 를 만듭니다. 이러한 동일한 런타임 호출 가능 래퍼는 나중에 MTA(다중 스레드 아파트)의 일부인 CLR의 종료자에 의해 제거됩니다. STA에서 MTA로 프록시를 이동하려면 마샬링이 필요하지만 확장에서 사용하는 모든 인터페이스를 마샬링할 수 있는 것은 아닙니다.
비결정적 개체 수명
CLR은 네이티브 코드보다 개체 수명 보장이 약합니다. 많은 확장에는 개체 및 인터페이스에 대한 참조 개수 요구 사항이 있으며 CLR에서 사용하는 가비지 수집 모델은 이러한 요구 사항을 충족할 수 없습니다.
- CLR 개체가 COM 개체에 대한 참조를 가져오는 경우 런타임 호출 가능 래퍼가 가비지 수집될 때까지 런타임 호출 가능 래퍼에서 보유한 COM 개체 참조가 해제되지 않습니다. 비결정적 릴리스 동작은 일부 인터페이스 계약과 충돌할 수 있습니다. 예를 들어 IPersistPropertyBag::Load 메서드를 사용하려면 Load 메서드가 반환될 때 개체에서 속성 모음에 대한 참조를 유지하지 않아도 됩니다.
- CLR 개체 참조가 네이티브 코드로 반환되면 런타임 호출 가능 래퍼의 Release 에 대한 최종 호출이 수행될 때 런타임 호출 가능 래퍼가 CLR 개체에 대한 참조를 포기하지만 기본 CLR 개체는 가비지 수집될 때까지 완료되지 않습니다. 비결정적 종료는 일부 인터페이스 계약과 충돌할 수 있습니다. 예를 들어 썸네일 처리기는 참조 수가 0으로 떨어질 때 모든 리소스를 즉시 해제해야 합니다.
관리 코드 및 기타 런타임의 허용 가능한 사용
관리 코드 및 기타 런타임을 사용하여 Out-of-process 확장을 구현할 수 있습니다. Out-of-process Shell 확장의 예는 다음과 같습니다.
- 미리 보기 처리기
- 셸\동사\ 명령 하위 키 아래에 등록된 작업과 같은명령줄 기반 작업입니다.
- Out-of-process 활성화를 허용하는 셸 확장 지점의 경우 로컬 서버에서 구현된 COM 개체입니다.
일부 확장은 in-process 또는 out-of-process 확장으로 구현할 수 있습니다. In-process 확장에 대한 이러한 요구 사항을 충족하지 않는 경우 이러한 확장을 out-of-process 확장으로 구현할 수 있습니다. 다음 목록에서는 in-process 또는 out-of-process 확장으로 구현할 수 있는 확장의 예를 보여 줍니다.
- 셸\동사\명령 하위 키 아래에 등록된 DelegateExecute 항목과 연결된 IExecuteCommand입니다.
- 셸\동사\DropTarget 하위 키 아래에 등록된 CLSID와 연결된 IDropTarget입니다.
- 셸\동사 하위 키 아래에 등록된 CommandStateHandler 항목과 연결된 IExplorerCommandState입니다.