실버라이트 개발자라면, 그리고 윈도 업데이트를 꼬박꼬박 하는 분이라면 현재 실버라이트 런타임 버전을 살펴보세요.
아마도 다음과 같이 4.0.60310.0으로 업데이트 되어 있을 거에요.

네, 쥐도 새도 모르게 조용~히 GDR4가 릴리즈되어 심지어 자동으로 설치까지 되었네요.
이번 업데이트는 조금은 특별한 사정이 있는데요, 우선 통상적인 버그 픽스 내용 부터 훑고 넘어가죠.

http://support.microsoft.com/kb/2526954

 

이번 업데이트로 수정된 이슈

이슈1

시나리오

  • HtmlPage.RegisterScriptableObject 메서드를 호출하여 스크립터블 타입을 등록합니다.
  • 실버라이트 4 애플리케이션을 실행하고 자바 스크립트 기반의 스크립트가 스크립터블 타입의 멤버에 접근할 수 있도록 합니다.
  • 애플리케이션이 모덜 윈도에 표시됩니다.

이 시나리오에서 다음의 경고 메시지를 받게 될 것입니다.

This page has an unspecified potential security risk. Would you like to continue?

(※한국어로는 뭐라고 나올지 모르겠네요.)

참고: 이 이슈는 보통 Microsoft Office 365 사용자가 Microsoft SharePoint Online을 이용할 때 나타납니다.

 

이슈2

시나리오

  • 실버라이트 4 애플리케이션에서 Control 클래스를 상속받는 사용자 컨트롤을 만듭니다. 이 사용자 컨트롤은 DefaultStyleKey를 오버라이드 하고 DependencyProperty를 하나 추가합니다.
  • 이 컨트롤의 ContentTemplate 속성은 팝업 컨트롤을 포함하고, 팝업 컨트롤은 ContentPresenter 오브젝트 한개만 포함합니다.
  • 이 오브젝트는 TemplateBinding 기능을 이용하여 앞서 만든 DependencyProperty 속성을 바인딩합니다.
  • 해당 팝업 컨트롤은 열리지 않을 것입니다.

이 시나리오에서 팝업 컨트롤의 메모리는 가비지 수집되지 않습니다. 때문에 메모리 누수가 나타납니다.

 

이슈3

시나리오

  • 인터넷 익스플로러 9를 이용하여 실버라이트 4 애플리케이션을 엽니다.
  • 윈도를 풀스크린 모드로 전환했다가 다시 원래 크기로 돌아옵니다.

이 시나리오에서 윈도의 내용이 제대로 표시되지 않을 수 있습니다. 예를 들어, 윈도에 빈 영역이 나타날 수 있습니다. 이 이슈는 BrowserInteropHelper 클래스가 호스트 HTML 페이지에 있는 자식 엘리먼트의 개수를 잘못 알려주기 때문입니다.

 

이슈4

실버라이트 4 애플리케이션이 DataGrid 컨트롤을 포함한다고 가정합시다. 컨트롤에 있는 각 컬럼의 크기는 다릅니다. 이 시나리오에서 컨트롤의 스크롤을 가로로 움직이면 컨트롤의 행이 잘못 표시됩니다.

 

이슈5

시나리오

  • DataGrid 컨트롤을 포함하는 실버라이트 4 애플리케이션을 실행합니다.
  • 이 컨트롤은 INotifyDataErrorInfo 인터페이스를 이용하여 유효성을 검사하는 타입을 바인딩합니다.
  • INotifyDataErrorInfo.ErrorsChanged 이벤트를 여러번 수신하게 됩니다.

이 시나리오에서 DataGrid 컨트롤의 메모리가 해제되지 않습니다. 때문에 메모리 누수가 나타납니다.

 

이슈6

실버라이트 4 애플리케이션에서 BindingExpression 인스턴스의 대상 엘리먼트가 DataGridCell 오브젝트에 들어있는 TextBlock 엘리먼트 또는 TextBox 엘리먼트라고 가정합시다. 이 상황에서 애플리케이션을 실행하여 해당 엘리먼트를 수정하면 DataGrid 컨트롤의 메모리가 해제되지 않습니다. 때문에 메모리 누수가 나타납니다.

 

이번 업데이트에 추가된 기능

이번 업데이트는 다음 경로의 레지스트리 키가 설정되어 있으면 IsolatedStorageExceptionInnerException 속성을 설정하는 기능을 추가합니다.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Silverlight\IsolatedStorageInnerExceptionsAllowedDomains

이 레지스트리 키의 값은 콤마(,)로 구분된 도메인 목록입니다.

 

몇몇 메모리 누수 문제를 해결하는 점에서는 꽤 중요한 문제지만, 사실 이것보다는 좀 더 재밌는 점들이 레이더(?)에 잡히네요^^

FirstFloor Software 운영자이자 마이크로소프트 실버라이트 MVP인 Koen Zwikstra씨가 이번 GDR4에서 새로 추가된(!) API를 정리했는데요, 다음 링크에 들어가보면 깔끔하게 정리되어 있어요.

http://firstfloorsoftware.com/files/DiffLists/Silverlight%204%20GDR%203-vs-Silverlight%204%20GDR%204.html

업데이트된 타입이 들어있는 네임스페이스는 총 6개.

  • System.Net.Sockets
  • System.Windows
  • System.Windows.Controls
  • System.Windows.Input
  • System.Windows.Media.Imaging
  • System.Windows.Navigation

그러나 재밌게도 이번 업데이트로 추가된 모든 기능은 MSDN 문서에서 “DO NOT USE”라고 심플하게만 설명되어 있을 뿐이죠. 실제로 비주얼 스튜디오에서도 해당 기능이 인텔리센스에 표시되지 않는지만, Reflector로 해당 어셈블리를 열어보면 존재하는 걸 확인할 수 있어요.

비밀은 바로 EditBrowsable 어트리뷰트! 이 어트리뷰트로 에디터(VS나 Blend)에서 해당 기능이 표시되지 않게 해놓은 것 뿐이죠.

아마도 이 기능들은 실버라이트 5를 위한 일종의 플레이스홀더(placeholder) 역할을 하는 걸로 보이는데요, 소켓에 UDP 필드가 추가된다거나 UIElement의 이벤트에 빌트인으로 Tap, DoubleTap, Hold가 추가된다거나, GestureEventArgs가 추가되는 등 상당히 흥미롭네요.

여튼 지금와서 이것들이 크게 영향을 주는건 아니고 다만 실버라이트 5가 빨리 나왔으면…하는 생각이에요. :)

저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo
요즘 너무 블로깅을 안했더니 거미줄이...
본격적인 글은 정신적인 여유가 안되어서 못쓰겠고 대충 메모라도 휘갈겨놓으려고해요.
'가상의' 독자를 상대로 얘기하고는 있지만 기본적으로는 잊지 않으려고 쓰는 '메모'의 용도에요.
친절하지 않은 글이니 관심 없는 분은 그냥 패~스.

Prism + MefExtension을 사용하면 내부적으로 IModuleManager로 MefModuleManager를 사용하는데, 요놈은 XAP 파일에 대한 IModuleLoader로써 다시 MefModuleTypeLoader를 사용하죠. 또한 이 모듈타입로더는 내부적으로 MEF에서 기본으로 제공하는 DeploymentCatalog를 이용해요. ...아 이 무슨 구약적 이름 소개인가; 누가 누구를 낳고 누구는 누구랑 친척이고...;;

여튼;

프리즘의 모듈매니저는 기본적으로 각 모듈과의 의존성 관계를 설정하여 의존성 있는 모듈이 먼저 초기화(Initialize)되도록 처리를 해주는 훌륭한 매커니즘을 가지고 있죠.
문제는 MEF가 기본으로 제공하는 DeploymentCatalog.
요놈은 XAP파일의 URI를 던져주면 알아서 다운로드를 받아 XAP 파일 내에 들어있는 어셈블리들을 죄다 런타임에 불러들인 후 지정된 카탈로그에 ExportPart를 뽑아서 관리해주는 역할까지 수행하죠.
그런데 여기서 문제가 이놈은 다운로드가 완료되면 무조건 위의 동작을 수행한다는거에요.

만약 다음과 같은 의존성을 갖는 솔루션 구성일 경우...
  • 기반 모듈
    • 데이터처리 모듈
      • 이메일 모듈
      • SMS 모듈
    • 그래픽 모듈
'이메일 모듈'은 '데이터처리 모듈'보다 나중에 초기화가 되어야 하죠.
네 실제로 모듈매니저는 의존성 관계를 통해 '데이터처리 모듈'을 먼저 초기화해요.
그런데, DeploymentCatalog에 의해서 각 모듈들이 다운로드 될 때 '이메일 모듈'이 먼저 다운로드가 완료된다면?
내부적으로 '이메일 모듈'을 까뒤집어서 그 안에 있는 ExportPart를 뽑아내려고 시도할거에요.
이 과정에서 '이메일 모듈'이 가지고 있는 '데이터처리 모듈'에 대한 의존성이 문제가 되어 그 시도는 처절한 예외 메시지를 내뱉고는 뻗어버리죠.

혹시 DeploymentCatalog의 소스 코드를 열어보신 분이라면(MEF preview때이건 리플렉터로 까봤건) 아래의 부분이 문제의 그곳. DiscoverParts 메서드의 구현중 일부에요. 밑줄친 부분이 아직 의존성이 해결되었을지 어떨지 알 수 없는 파트를 접근하려는 곳.

foreach (Assembly assembly in assemblies)
{
    if (!dictionary.ContainsKey(assembly.FullName))
    {
        AssemblyCatalog catalog = new AssemblyCatalog(assembly);
        addedDefinitions.AddRange(catalog.Parts);
        dictionary.Add(assembly.FullName, catalog);
    }
}

휘유... 여기까지가 아래에 올린 Don't Panic의 내용을 재현한 거에요.
이게 적당히 다운로드 순서를 바꿔주는 것 만으로는 근본적인 해결이 안되네요.
아무래도 MEF의 DeploymentCatalog를 조금 바꿔서 써야겠어요.
그러려면;; 다시 이걸 사용하는 MefModuleManager를 바꿔야 하고 여기에 연관되어 있는 MefModuleInitializer, MefXapModuleTypeLoader도 모두 조금씩은 바꿔야겠죠; 하아...

그나마 소스 공개되어 있는게 얼마나 다행인지. 오픈소스 만세! 리플렉터 만만세!
저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo
참 뭐랄까 근본 없는 것이란 이런 기초적인데에서 문제를 드러내지요.
그러니까... 보통 예외 메시지들이란게 대체로 별로 도움이 안되는 경우가 많잖아요?
누가 null reference 들어와서 죽은거 모른대요? 왜 null이 들어왔는지를 모르는거죠.

여튼.

이런 경험이 누적되다보면 예외 메시지는 Exception.Message만 대충 보고 다른데서 원인을 찾기 마련인데요.
가끔은 Exception.InnerException을 보고도 더 많은 정보를 얻을 수 있는 기회를 놓칠 때가 있어서 다시는 잊지 말자는 심정으로 포스팅해요.

이번 케이스는 이것.

동적으로 XAP 파일을 받아서 동적으로 어셈블리들을 로드하는데 분명히 해당 어셈블리 중 하나의 의존성이 해결되지 않아서 발생하는 문제인것까진 알겠는데 어떤 어셈블리의 문젠지를 모르겠단 말이에요. 아주 한참을 헤맸죠.

던져주는 메시지라곤 고작 "Unable to load one or more of the requested types. ..."
네, 참 도움 되네요. 로드하다 실패해놓고 로드에 실패했다니;;; 어쩌라고!

뭘 놓쳤는지 아시겠죠? 뒤에 ...으로 더 이상 읽지 않은 부분이 바로: "Retrieve the LoaderExceptions property for more information." 근데 여기에서  InnerException이 null 이라서 '더 많은 정보'가 어디에 있는지를 모르고 지나치기 일쑤란거죠.
사실은 여기에서 받은 예외의 원래 타입은 System.Reflection.ReflectionTypeLoadException이죠. 근데 그 예외를 그냥 Exception 타입으로 받아와서 ReflectionTypeLoadException이 가지고 있던 고유의 데이터는 다음과 같이 숨겨져 버린거죠.


아;; 친절하게도 무려 한글 오류씩이나;;
네, 타입 로드에 실패한 원인은 System.Windows.Controls.Data 어셈블리가 미리 로드 되지 않아서였군요.
컴파일 시점에는 드러나지 않았던 의존 관계라서 디버깅에 참 애를 먹었어요.

요즘 Prism 4 + MEF로 프로젝트 진행중인데 동적 로딩을 많이 사용해서 생각지도 못한 에러가 많아요.
그나마 비주얼 스튜디오가 아니었으면 이런 에러는 어떻게 잡나 싶을 정도로요.
어쨌든!

Don't Panic!
저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo
참 뭐랄까 근본 없는 것이란 이런 기초적인데에서 문제를 드러내지요.
그러니까... 보통 예외 메시지들이란게 대체로 별로 도움이 안되는 경우가 많잖아요?
누가 null reference 들어와서 죽은거 모른대요? 왜 null이 들어왔는지를 모르는거죠.

여튼.

이런 경험이 누적되다보면 예외 메시지는 Exception.Message만 대충 보고 다른데서 원인을 찾기 마련인데요.
가끔은 Exception.InnerException을 보고도 더 많은 정보를 얻을 수 있는 기회를 놓칠 때가 있어서 다시는 잊지 말자는 심정으로 포스팅해요.

이번 케이스는 이것.

동적으로 XAP 파일을 받아서 동적으로 어셈블리들을 로드하는데 분명히 해당 어셈블리 중 하나의 의존성이 해결되지 않아서 발생하는 문제인것까진 알겠는데 어떤 어셈블리의 문젠지를 모르겠단 말이에요. 아주 한참을 헤맸죠.

던져주는 메시지라곤 고작 "Unable to load one or more of the requested types. ..."
네, 참 도움 되네요. 로드하다 실패해놓고 로드에 실패했다니;;; 어쩌라고!

뭘 놓쳤는지 아시겠죠? 뒤에 ...으로 더 이상 읽지 않은 부분이 바로: "Retrieve the LoaderExceptions property for more information." 근데 여기에서  InnerException이 null 이라서 '더 많은 정보'가 어디에 있는지를 모르고 지나치기 일쑤란거죠.
사실은 여기에서 받은 예외의 원래 타입은 System.Reflection.ReflectionTypeLoadException이죠. 근데 그 예외를 그냥 Exception 타입으로 받아와서 ReflectionTypeLoadException이 가지고 있던 고유의 데이터는 다음과 같이 숨겨져 버린거죠.


아;; 친절하게도 무려 한글 오류씩이나;;
네, 타입 로드에 실패한 원인은 System.Windows.Controls.Data 어셈블리가 미리 로드 되지 않아서였군요.
컴파일 시점에는 드러나지 않았던 의존 관계라서 디버깅에 참 애를 먹었어요.

요즘 Prism 4 + MEF로 프로젝트 진행중인데 동적 로딩을 많이 사용해서 생각지도 못한 에러가 많아요.
그나마 비주얼 스튜디오가 아니었으면 이런 에러는 어떻게 잡나 싶을 정도로요.
어쨌든!

Don't Panic!
저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo


티스토리 툴바