참 뭐랄까 근본 없는 것이란 이런 기초적인데에서 문제를 드러내지요.
그러니까... 보통 예외 메시지들이란게 대체로 별로 도움이 안되는 경우가 많잖아요?
누가 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
실버라이트 개발 중 겪는 숱한 에러 메시지와 익셉션들 그리고 공포의 화이트 스크린(!!)...
이런 문제들을 정리하기 위해 Error1001.com이 개장했어요.
실은 개장한지 한참 되긴 했는데 공지만 덜렁 있으면 너무 썰렁하잖아요? ^^;

Error1001은 실버라이트 1.0과 1.1 시절에 개발자들을 패닉에 빠지게 하는 불친절한 에러메시지에서 따온 이름이에요. 아마 그시절 실버라이트 개발자라면 Error code 1001의 분노를 아직 기억하실거에요.


실버라이트 개발자들의 분노를 샀던 바로 이 메시지 박스(크아아아아아!!)

실버라이트는 아직 역동적으로 발전하고 있는 플랫폼이기 때문에 다소 거슬리는 버그나 오류도 많이 가지고 있죠. Error1001에서 서로의 경험을 공유할 수 있으면 좋겠어요. Error1001은 팀블로그로 운영되고 필자가 되고 싶은 분은 언제든지 Error1001의 공지에 비밀 댓글을 남겨주세요. :)
신고
Posted by gongdo
사용자 삽입 이미지

한창 할 것도 많은데 난데없는 시리즈 예고,
DON'T PANIC!
쫄지 마세요!

뭐든 프로그래밍하다보면 하란대로 했는데, 어제만 해도 잘 돌았는데, 붙여넣었을 뿐인데도 런타임 오류며, 예외며 오동작이며 가지 각색의 버그를 만나잖아요?

이 시리즈는 실버라잇을 하면서 접할 수 있는 다양한 문제점들에 대한 원인과 해결책에 대해서 다룰 예정이에요.

지금은 한 서너개 정도 케이스가 있는데 오늘은 졸려서 시리즈 예고만. : )
신고
Posted by gongdo
Silverlight 1.1 바로 시작하기

디버깅과 예외 처리
준비 사항
Silverlight 개발의 기초에서 개발에 필요한 도구와 기술에 대해 설명하고 있습니다.
이벤트 핸들링에서 개체의 이벤트를 처리하는 방법에 대해 설명하고 있습니다.
커스텀 컨트롤에서 개발 프로젝트에 테스트 프로젝트를 추가하는 방법을 소개하고 있습니다.

기본적으로 Visual Studio IDE를 사용한 .Net 프로그래밍 및 디버깅 방법과 유사하므로 Visual Studio IDE를 사용한 보다 전문적인 디버깅은 Visual Studio의 디버깅을 참고하십시오. 이 글에서는 간단한 기법만을 소개합니다.

또한 ASP.NET 프로젝트와 IIS에 대한 언급도 나옵니다. 이 부분은 지금 곧 사용하지 않는다면 특별한 사전 지식은 필요 없습니다.

매니지드 코드 디버깅

일반적인 브레이크 포인트를 사용한 디버깅
매니지드 코드의 디버깅은 일반적인 .Net 프로그래밍에서의 그것과 동일합니다. 가장 기본적인 디버깅 방법으로 브레이크 포인트를 걸고 런타임에 해당 코드가 실행되기 직전에 코드의 실행을 멈추고 콜스택이나 멤버 변수 등의 값을 살펴볼 수 있습니다.

우선 매니지드 코드 디버깅 예제를 위해 새 프로젝트를 생성하고 일부러 틀린 코드를 넣어보겠습니다.
Howto:4-1 새 프로젝트에 잘못된 코드 작성하기
1. 새 프로젝트를 생성합니다. (프로젝트를 생성하는 방법은 Silverlight 개발의 기초를 참고하십시오.)
2. Page.xaml.cs의 Page 클래스에 다음과 같은 멤버 함수를 작성하고 Page_Loaded에서 해당 함수를 호출합니다.
C#
private void WrongMethod()
{
    TextBlock tb = new TextBlock();
    Run run = new Run();
    run.Text = "Test text";
    tb.Inlines.Add(run);
    this.Children.Add(tb);
}

위의 코드를 언뜻 보면 새 TextBlock 개체를 생성하고 TextBlock에 Run 텍스트를 하나 추가한 후 TextBlock을 페이지의 자식 개체로 추가하는 정상적인 코드처럼 보입니다. 아마도 개발자는 화면에 Test text 란 메시지가 출력되길 기대하고 있을 것입니다.

하지만 F5를 눌러 위의 코드를 디버그 모드로 실행해보면 화면에는 아무것도 나오지 않으며 다만 Output 창에는 예외가 발생했다는 메시지가 보입니다.


문제가 발생하는 시점을 찾기 위해 브레이크 포인트를 걸고 차근차근 진행해 보겠습니다.
Howto:4-2 브레이크 포인트 걸고 진행하기
1. 어디에서 문제가 생겼는지 확실치 않으므로 처음부터 브레이크 포인트를 설정합니다. 첫 문장인 TextBlock tb = new TextBlock() 코드에 커서를 맞추고 F9를 누르거나 해당 라인의 제일 왼쪽의 회색 공간을 클릭하여 브레이크 포인트를 설정합니다.


2. F5를 눌러 디버그 모드로 실행하면 다음과 같이 브레이크 포인트에서 코드 실행이 멈춥니다.


3. F10을 눌러 한 라인 단위로 진행합니다. (※노트: 함수 내부까지 들어가서 진행하려면 F11을 눌러 진행합니다.)

4. 아마도 tb.Inlines.Add(run); 문장을 진행하면 Output 창에 예외가 발생하였다는 메시지와 함께 디버깅이 중지되고 미완성된 페이지가 브라우저에 나타날 것입니다.

5. Shift + F5를 누르거나 디버깅 중인 브라우저를 닫아 디버깅 모드를 완전히 종료합니다.

6. 4번 과정을 실행하는 중 예외가 발생하였으므로 이 부분의 코드가 잘못되었다는 것을 알 수 있습니다. 또한 예외 메시지를 살펴 보면 [A first chance exception of type 'System.NullReferenceException' occurred in DebugManagedCode] 즉, 예외의 종류가 System.NullReferenceException임을 알 수 있고 자연스럽게 null을 참조하여 발생한 문제라는 것도 예상할 수 있습니다.

7. 다시 한번 디버깅을 진행하여 주의 깊게 진행하고 4번 과정에서 진행하지 않고 멈춰서 tb.Inlines 부분에 마우스 커서를 맞추면 다음과 같이 상세 정보를 볼 수 있습니다. 예상대로 tb.Inlines 멤버가 null을 참조하고 있으며 따라서 Inlines의 멤버 메소드인 .Add를 접근할 수 없음을 알 수 있습니다.
 

위의 시나리오는 비교적 간단하고 사소한 실수이지만 코드를 작성할 때 빈번하게 발생하는 문제이기도 합니다. 보통 코드를 작성하고 최초로 테스트 할 때에는 위와 같이 새로 작성한 코드에 브레이크 포인트를 설정하여 한 라인씩 진행하면서 코드가 예측한대로 작동하는지 검사하곤 합니다.

Visual Studio IDE는 디버그 모드상에서 어떤 개체에 대해 매우 직관적이고 상세한 정보를 실시간으로 볼 수 있는 인터페이스를 제공하고 있습니다. 각 개체는 자신의 멤버 뿐만 아니라 자신의 상위 개체에 대한 정보도 볼 수 있습니다.

브레이크 상태에서 코드를 직접 실행하기
브레이크가 걸린 상태에서 IDE에는 직접 실행 창(Immediate Window)이 나타납니다. 이 직접 실행 창에서는 현재 코드 상태에서 멤버의 값을 변경하거나 읽어오는 등 즉시 코드를 실행할 수 있습니다. 특히 임의의 식(expression)을 테스트 해볼 수도 있어서 디버깅에 매우 유용한 툴입니다.

Howto:4-3 직접 실행 창에서 디버깅 하기
1. 이전 예제를 디버깅 모드로 실행하고 브레이크 상태를 만든 후 문제의 코드까지 진행합니다. IDE의 하단에서 직접 실행 창(Immediate Window) 탭을 찾아 엽니다.

2. 직접 실행 창에 다음과 같이 입력하고 엔터를 눌러 tb.Inlines의 값을 확인해 봅니다.
Immediate Window
? tb.Inlines.ToString();


tb.Inlines가 null임을 확인할 수 있습니다. 여기에서 '?'는 직접 실행 창에 그 결과를 출력하라는 의미입니다.

3. 직접 실행 창에 다음과 같이 입력하고 엔터를 눌러 tb.Inlines의 새 인스턴스를 할당해 봅니다.
Immediate Window
tb.Inlines = new Inlines();



4. 개체 참조가 변경되었는지 확인하기 위해 다시 한번 tb.Inlines의 내용을 출력해봅니다.


5. F5를 눌러 코드를 계속 진행합니다. 아까와는 다르게 예외가 발생하지 않고 정상적인 출력이 된 것을 확인할 수 있습니다.


직접 실행 창을 사용하면 런타임 도중에 문제가 생겼다고 예상되는 지점에서 직접 코드를 테스트해볼 수 있습니다. 여기에서 이미 작성된 코드 뿐만 아니라 위의 예제와 같이 new 연산자 등을 통해 개체의 새 인스턴스를 생성하는 것도 가능하며 코드와 전혀 관계 없는 수식 등도 사용할 수 있습니다.

예외 처리
브레이크 포인트와 직접 실행 창을 사용한 디버깅은 개발 초기에는 문제점을 찾기에 매우 유용하지만 애플리케이션이 배포되고 난 후에는 전혀 도움이 되지 않습니다. 애플리케이션은 미처 수정하지 못한 문제점이 있기 마련이며 코드가 완벽하더라도 외부 환경적인 요인으로 인해 문제가 발생할 수도 있습니다.

예를 들어, 외부 리소스 XAML 파일의 스트림을 읽어오는 코드를 생각해보면 이 XAML 파일은 외부 컨텐츠이므로 해당 경로에 존재하지 않을 수도 있을 것입니다. 이렇게 동적으로 상태가 변경될 수 있는 가능성이 있는 코드는 반드시 예외 처리를 할 필요가 있으며 Silverlight 매니지드 코드에서는 전통적인 try~catch~finally문을 지원합니다.
Howto:4-4 예외가 발생할 수 있는 코드를 위한 try~catch 예제
1. Page.xaml.cs에 다음과 같이 System.IO 네임스페이스를 추가합니다.
C#
using System.IO;

2. Page 클래스에 다음과 같은 멤버 메소드를 작성하고 Page_Loaded에서 해당 메소드를 호출하는 코드를 추가하고 이전 예제인 WrongMethod() 호출은 주석처리 합니다.
C#
private void ExceptionalMethod()
{
    StreamReader sr = null;
    try
    {
        sr = new StreamReader("test.xaml");
        Brush dynamicBrush = (Brush)XamlReader.Load(sr.ReadToEnd());
        sr.Close();
    }
    catch (Exception ex)
    {
        string err = ex.Message;
    }
}

3. 프로젝트 폴더에 test.xaml이란 파일은 존재하지 않으므로 예외가 발생하고 catch 될 것을 예상할 수 있습니다. string err = ex.Message; 문장에 브레이크 포인트를 설정하고 F5를 눌러 프로젝트를 디버깅 모드로 실행해 봅니다.

4. IDE상의 직접 접근과 직접 실행 창 등을 통해 예외 정보 개체인 ex를 통해 예외의 정보에 접근할 수 있습니다.

코드에서 예외가 발생하면 그 다음 문장은 실행되지 않고 코드가 중지되어버리기 때문에 웹 애플리케이션의 관점에서 최악의 상황이라고 할 수 있습니다. 따라서 런타임 중 예외가 발생할 가능성이 있는 코드는 반드시 위와 같은 try~catch 문을 사용하여 예외가 발생했을 때 애플리케이션이 그냥 중지되어버리지 않도록 처리할 필요가 있습니다.

브레이크 포인트를 걸지 않고 정보 출력하기
매우 빈번하게 진행되는 코드의 디버깅을 브레이크 포인트로 한 줄씩 실행한다는 것은 너무나도 소모적인 일입니다. 보다 효율적인 디버깅을 위해 Silverlight는 System.Diagnostics 네임스페이스에 포함된 Debug 클래스를 제공합니다.


이 클래스는 디버깅 도중 브레이크 포인트를 걸지 않고도 Output 창에 문자열을 출력할 수 있는 WriteLine 메소드를 지원하며 WriteLine 메소드는 콘솔 애플리케이션의 Console.WriteLine 메소드와 동일한 사용법을 가졌습니다.
노트
아쉽게도, 매우 강력한 디버깅 도구인 Debug.Assert는 현재 제대로 작동하지 않는 것으로 보입니다. Assert는 코드의 전제 조건을 강제하고 조건이 실패하는 경우 코드의 실행을 멈추고 지정한 메시지를 출력하는 역할을 수행하는 메소드입니다. 하지만 Silverlight 1.1 Alpha(2007.5 CTP) 현재는 Assert에 어떤 조건을 걸어도 별도의 리액션이 발생하지 않습니다.

Howto:4-5 Debug.WriteLine 메소드
1. Page.xaml.cs에 다음과 같이 System.Diagnostics 네임스페이스를 추가합니다.
C#
using System.Diagnostics;

2. Page 클래스에 다음과 같은 멤버 메소드를 작성하고 Page_Loaded에서 해당 메소드를 호출하는 코드를 추가하고 이전의 두 예제 메소드는 주석처리 합니다.
C#
private void OutputMethod()
{
    int sum = 0;
    for (int i = 1; i <= 100; ++i)
    {
        sum += i;
        Debug.WriteLine("i = {0}, sum = {1}", i, sum);
    }
    Debug.WriteLine("Total = {0}", sum);
}

3. F5를 눌러 실행합니다. IDE의 Output 창에 다음과 같이 출력되었음을 확인할 수 있습니다.

지금까지 테스트했던 프로젝트를 첨부하였습니다.
DebugManagedCode.zip

매니지드 코드 디버깅



웹 프로젝트와 Silverlight 프로젝트를 함께 디버깅

Silverlight는 JavaScript를 사용하여 HTML 페이지에 호스트되는 클라이언트 사이드 애플리케이션이기 때문에 서버 사이드는 어떤 언어를 사용하여도 상관 없습니다. 하지만 Silverlight 컨트롤을 ASP.NET 페이지에 호스팅하도록 개발한다면 하나의 개발환경과 CLR을 통해 제공되는 일관된 언어 사용의 장점을 얻을 수 있을 것입니다.

이때 Silverlight 컨트롤이 자신을 호스팅하는 ASP.NET 페이지와 상호작용이 많다면 ASP.NET 페이지와 Silverlight 컨트롤의 코드를 함께 디버깅할 수 있으면 편리할 뿐더러 생산성도 대폭 향상될 것입니다.

이 절에서는 ASP.NET 웹 프로젝트에서 Silverlight 프로젝트를 추가하여 함께 디버깅하는 방법을 알아보겠습니다.

먼저 아주 간단하게 Hello Silverlight!를 출력하는 Silverlight 프로젝트를 하나 작성합니다. 이제 프로젝트 작성에 익숙해졌으리라 믿고 생성하는 방법은 생략하겠습니다. 프로젝트 이름은 HelloSilverlight라고 하겠습니다.
Howto:4-6 웹 프로젝트와 Silverlight 프로젝트를 링크하고 디버깅하는 방법
1. Visual Studio를 실행하고 메뉴에서 File->New->Project를 선택하거나 Ctrl+Shift+N을 눌러 새 프로젝트를 선택합니다.

2. Project Type에서 Visual C#->Web을 선택하고 Templates에서 ASP.NET Web Application을 선택한 후 프로젝트 이름을 MixedModeDebug라고 적고 [OK]를 누릅니다.
사용자 삽입 이미지


3. 솔루션 익스플로러의 솔루션 아이템에서 마우스 오른쪽 버튼을 누르고 Add->Existing Project를 선택합니다.


4. 미리 만들어둔 HelloSilverlight 프로젝트를 선택합니다. 솔루션 익스플로러에 이제 두개의 프로젝트가 포함될 것입니다.

5. 솔루션 익스플로러의 MixedModeDebug 웹 프로젝트에서 마우스 오른쪽 버튼을 누르고 Add Silverlight Link를 선택합니다.


6. 목록에 HelloSilverlight가 있을 것입니다. 선택하고 [OK]를 누릅니다.


7. 이 프로젝트를 위한 Silverlight 디버깅을 활성화 하겠냐고 묻는 창이 나옵니다. [예]를 누릅니다.
사용자 삽입 이미지

중요
이 설정은 스크립트 디버깅을 비활성화 상태로 설정합니다. Mixed-mode 디버깅을 사용하는 상태에서 매니지드 코드와 언매니지드 코드(스크립트)를 동시에 디버깅 할 수 없습니다.

8. 다음과 같이 MixedModeDebug 웹 프로젝트에 ClientBin과 Page.xaml 파일이 복사되었음을 확인할 수 있습니다.


9. Page.xaml을 ASP 페이지로 로드하기 위해 Silverlight.js와 createSilverlight 함수를 프로젝트로 추가합니다. 실제 프로젝트에서 Silverlight.js는 아마 웹서버의 공용 include 폴더에 위치할 것이며 createSilverlight 함수는 각 XAML 파일마다 하나씩 존재할 것입니다. 여기에서는 빠른 진행을 위해 HelloSilverlight 프로젝트의 Silverlight.js와 createSilverlight 함수가 포함된 TestPage.html.js 파일을 프로젝트로 추가하고 MixedModeDebug 웹 프로젝트의 Default.aspx에 위 스크립트 파일들을 include하고 Page.xaml을 로드할 것입니다.

솔루션 익스플로러의 MixedModeDebug 웹 프로젝트에서 마우스 오른쪽 버튼을 누르고 Add Existing Item을 선택하고 HelloSilverlight 프로젝트의 Silverlight.js 파일과 TestPage.html.js 파일을 선택합니다.



10. 다음과 같이 MixedModeDebug 웹 프로젝트에 해당 파일이 복사되었음을 확인할 수 있습니다.


11. HelloSilverlight 프로젝트의 TestPage.html 파일을 열어 스크립트를 include 하는 부분과 XAML을 로드하는 HTML 코드를 복사하여 MixedModeDebug 웹 프로젝트의 Default.aspx파일에 붙여넣습니다.
사용자 삽입 이미지


12. 양쪽 프로젝트에 모두 브레이크 포인트가 잡히는지 확인하기 위해 MixedModeDebug 웹 프로젝트의 Default.aspx.cs 파일에서 Page_Load 메소드에 브레이크 포인트를 설정하고 HelloSilverlight 프로젝트의 Page.xaml.cs 파일에 Page_Loaded 메소드에 브레이크 포인트를 설정합니다.


13. Ctrl+Shift+B 또는 F6을 눌러 솔루션을 빌드하고 F5를 눌러 디버깅 모드로 실행해 봅니다.
이때 Web.config 파일에 디버깅이 활성화되지 않았다는 메시지가 나올 것입니다. [Modify Web.config file to enable debugging.]을 선택하고 [OK]를 누릅니다.


14. 정상적인 경우 MixedModeDebug 웹 프로젝트의 Default.aspx.cs 파일에 먼저 브레이크가 걸리고 계속 진행하면 HelloSilverlight 프로젝트의 Page.xaml.cs 파일에 브레이크가 걸릴 것입니다.

웹 프로젝트에서 JavaScript 디버깅

앞서 소개한 디버깅 기법으로 웹 프로젝트와 Silverlight를 통합된 환경에서 디버깅할 수 있지만 이렇게 할 경우 다른 JavaScript 등의 스크립트 디버깅 기능은 사용할 수 없게 됩니다. 이 절에서는 이 전 절의 솔루션 상태에서 Silverlight 디버깅을 제거하고 JavaScript 디버깅을 하는 방법에 대해 알아보겠습니다.
Howto:4-7 웹 프로젝트에서 JavaScript 디버깅하는 방법
1. 먼저 인터넷 익스플로러를 디버깅 가능한 상태로 설정해야 합니다.
인터넷 익스플로러의 도구 메뉴에서 인터넷 옵션을 선택합니다.

2. 고급 탭에서 '스크립트 디버깅 사용 안 함(Internet Explorer)'의 체크를 해제합니다. 만약 다른 브라우저로도 디버깅하려면 '스크립트 디버깅 사용 안 함(기타)'의 체크도 해제합니다.

3. '모든 스크립트 오류에 관련된 알림 표시'를 체크합니다.

4. 'HTTP 오류 메시지 표시'의 체크를 해제합니다.

5. MixedModeDebug 웹 프로젝트의 Default.aspx의 body 태그에 테스트를 위해 다음과 같은 JavaScript 코드를 추가합니다.
JavaScript
<script type="text/javascript">
    var today = Date();
    alert(today.toString());
</script>

6. 솔루션 익스플로러의 MixedModeDebug 웹 프로젝트에서 마우스 오른쪽 버튼을 누르고 Properties를 선택하거나 Properties 항목을 더블 클릭합니다.

7. Web 탭의 Debuggers 섹션에서 Silverlight의 체크를 해제합니다.
사용자 삽입 이미지


8. 속성 패널을 닫고 5번 과정에서 추가한 JavaScript 코드에 브레이크 포인트를 추가합니다.

9. 솔루션을 빌드하고 F5를 눌러 디버깅 모드로 실행합니다.

10. 다음과 같이 JavaScript에서 브레이크가 걸리고 줄 단위 혹은 코드 단위 진행이 가능합니다.

여기까지 작성된 프로젝트를 첨부합니다.
MixedModeDebug.zip

MixedMode 디버깅과 JavaScript 디버깅



IIS를 사용한 디버깅

기본적으로 ASP.NET 페이지 프로젝트는 Visual Studio의 가상 웹서버를 통해 호스팅됩니다. 실제 프로젝트에서는 IIS와 연동을 통한 테스트를 직접 수행할 수 있습니다.
Howto:4-8 IIS를 사용한 디버깅
1. MixedModeDebug 웹 프로젝트에서 마우스 오른쪽 버튼을 누르고 Properties를 선택하거나 Properties 항목을 더블 클릭합니다.

2. Web 탭의 Servers 섹션에서 Use IIS Server를 체크합니다. 이 옵션은 반드시 IIS 서버가 사용 가능한 상태여야 합니다.

3. Create New Virtual Directory를 클릭하고 새로 생성할 디렉토리의 정보를 입력합니다.

4. 속성 패널을 닫고 모두 저장합니다.
이제 실제 IIS 서버를 사용하여 디버깅을 할 수 있습니다.

참고

Silverlight 공식 QuickStarts 참고:
http://silverlight.net/QuickStarts/Start/Debug.aspx

Visual Studio 디버깅 참고:
http://msdn2.microsoft.com/ko-kr/library/sc65sadd(VS.80).aspx
신고
Posted by gongdo
후우... 이걸 몰라서 헤맨 시간을 생각하면 안습.

CImageList의 Create 메소드에서 다음과 같이 사용.

CImageList img;
img.Create(16, 16, ILC_COLOR|ILC_MASK, 1, 1);

중요한건 ILC_MASK!!
MASK가 빠지면 바탕색이 기본 BackGround색인 검정색이 됨.
신고
Posted by gongdo
TAG 디버깅
▶ 문제 코드
[환경]
OS : Windows 98
Language : Visual Basic 6.0 SP6
참고 : Paul Caton의 Self-SubClassing 기법(http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=54117&lngWId=1)

[소스 코드]
// 상세 생략 //
VB폼의 hWnd를 넘겨서 Subclass_Start()을 호출하여 서브클래싱을 시작하고
Subclass_AddMsg()로 몇 가지 메시지를 추가한 후 Subclass_Stop()을 호출.

▶ 문제점
- Windows 2000, XP 등 에서는 전혀 문제가 없지만 같은 코드를 Windows 98에서 실행할 경우 APP가 완전히 종료된 후 Memory Access Violation이 발생함
- APP 자체의 동작이나 서브 클래싱은 모두 정상적으로 작동하나 APP가 종료되는 시점에서 치명적으로 보기 좋지 않은 메시지를 보여주므로 문제.
- VB폼의 hwnd가 아닌 CreateWindow()등의 API로 생성한 윈도에서는 문제가 발생하지 않는 것으로 보임(정확하진 않음)

▶ 해결 과정
시도1 : 복잡한 서브 클래싱 과정을 최소로 줄여 SubClass_Start(), Stop()만 호출하여 테스트
여전히 같은 증상 발생.

시도2 : 라인 단위의 길고 지루한 트레이스를 통해 정상적으로 실행되지 않은 코드가 있는지 하나하나 체크... 별 다른 이상은 없음.

시도3 : 내부적으로 사용되는 GlobalAlloc(), VirtualProtect(), GlobalFree() 등의 동작 체크, 이상 없음.

시도4 : Paul Caton의 새 업데이트 없는지 확인. 없음.

시도5 : Self-SubClass 자체의 문제가 있다고 판단하고 다른 코드로 교체.
- 대체할 코드로 역시 Paul Caton이 작성한 WinSubHook.tlb 모듈을 사용.
- WinSubHook.tlb는 Self-SubClass에 비해 디자인 타임 의존성이 추가된다는 단점이 있지만 소스 코드는 훨씬 단순화 되므로 TLB 관리만 잘 한다면 큰 문제가 없을 것으로 생각됨.
- 같은 동작을 하는 코드를 WinSubHook TLB의 iSubClass 인터페이스를 통하여 구현, 2000, 98 모두 잘 동작하고 Access Violation도 발생하지 않음.

▶ 정리
- Paul Caton의 Self-SubClass 기법은 98에서 약간의 문제가 있는 것으로 판단됨.
- vbAccelerator.com에 올라온 Paul Caton의 WinSubHook TypeLibrary로 교체하여 해결함.
링크 : TLB 다운로드(http://www.vbaccelerator.com/home/VB/Type_Libraries/WinSubHook/article.asp)
WinSubHook 예제 및 설명(http://www.vbaccelerator.com/home/VB/Code/Libraries/Subclassing_and_Hooking_with_Machine_Code_Thunks/article.asp)
신고
Posted by gongdo

▶ 문제 코드
[환경]
OS : Windos 2000, 98(VMWare)
Language : Visual Basic 6.0 SP6
참고 : 순수 Win32 API 코드이므로 다른 언어에서도 같은 증상이 있을 것이라고 생각됨

[소스 코드]

▼ 소스코드 보기

▶ 문제점
- 같은 머신 상에서 시리얼 포트 체크를 위해 CreateFile()을 호출할 때 Windows 2000, XP일 경우 정상적인 핸들을 반환하였으나 Windows 98에서는 완전히 같은 코드로도INVALID_HANDLE_VALUE를 반환함.

▶ 해결 과정
시도1 : 일단 API 레퍼런스를 참고하여 의심되는 파라미터를 변경해 봄.

▼ CreateFile 정보

여전히 같은 증상, 시리얼 통신과 관련된 어떤 파라미터나 플래그 값으로도 같은 증상

시도2 : 구글링으로도 정확히 같은 증상은 없고 비슷하거나 반대의 케이스는 몇몇 보임
시도3 : 고심중 언뜻 스치고 지나간 생각, Win98은 SECURITY_ATTRIBUTES를 사용할 수 없다!!
따라서 CreateFile()에서 lpSecurityAttributes에 NULL을 주면 해결되지 않을까...
그런데 VB의 표준 CreateFile() 선언에서는 lpSecurityAttributes가 Byref로 잡혀있어서 NULL을 줄 수 없었던 것.
CreateFile() 선언은 그대로 두고 NULL 파라미터를 줄 수 있는 CreateFileNull()이란 이름으로 따로 선언하고 lpSecurityAttributes에 VB에서의 NULL인 0&를 주었더니 아무 문제 없이 해결됨.

Private Declare Function CreateFile Lib "kernel32.dll" Alias "CreateFileA" _
  (ByVal lpFileName As String, _
  ByVal dwDesiredAccess As Long, _
  ByVal dwShareMode As Long, _
  ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES, _
  ByVal dwCreationDisposition As Long, _
  ByVal dwFlagsAndAttributes As Long, _
  ByVal hTemplateFile As Long) As Long

- 위에서 굵게 표시한 부분을 다음과 같이 수정
▶ Byval lpSecurityAttributes As Long
- CreateFile을 호출 할 때 SECURITY_ATTRIBUTES 구조체를 인수로 줬던 부분을 0&로 수정


▶ 정리
- 이 외에도 Win98에서 security_attributes를 요구하는 API를 쓸때는 각별한 주의가 필요함.
- 수정된 완전한 소스 코드

▼ 소스코드 보기

신고
Posted by gongdo


티스토리 툴바