블로그 이미지
따뜻한 코드 만들기 리본매냐

카테고리

분류 전체보기 (34)
.NET (6)
Database (5)
Daily life (11)
세미나 후기 (0)
마음의 지식 (7)
코드 (1)
Python (1)
외출 (3)
Total41,574
Today12
Yesterday2

달력

« » 2019.7
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

공지사항

태그목록

public partial class Form2 : Form

    {

        public const int SW_SHOWNOACTIVATE = 4;

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        public Form2()

        {
            InitializeComponent();
        }

        public void MyShow()
        {
            ShowWindow(this.Handle, SW_SHOWNOACTIVATE);
        }

    } 


SW_HIDE : 윈도우를 숨기며 다른 윈도우를 활성화 한다.

SW_MAXIMIZE : 윈도우를 최대화 시킨다.

SW_MINIMIZE : 윈도우를 최소화 시킨다.

SW_RESTORE : 최대, 최소화된 윈도우를 이전 위치로 복구한다.

SW_SHOW : 현재 크기와 위치에서 윈도우를 활성화 하면서 보인다.

SW_SHOWDEFAULT : STARTUPINFO 구조체가 지정하는 보이기 상태로 만든다.

SW_SHOWMAXIMIZED : 윈도우를 최대화 된 상태로 활성화 한다.

SW_SHOWMINIMIZED : 윈도우를 최소화 한 상태로 활성화 한다.

SW_SHOWNA : 윈도우를 현재 상태로 보이며 활성화 상태가 변경되지 않는다.

SW_SHOWNOACTIVATE : 가장 최근 크기와 위치에 윈도우를 보인다.

SW_SHOWNORMAL : 윈도우를 보이며 활성화 한다.

Posted by 리본매냐


.NET 으로 만든 응용프로그램에서 com 객체를 호출한 경우 Windows7 64bit 에서 제목과 같은 에러가 발생했다.
Win32 COM 과 .NET 프로그램간의 호환성 때문에 생긴 문제였다.
원인은 .NET 실행시 JIT 컴파일러에 의해 최적화된 기계어로 변환되기 때문.. Win32 COM은 컴파일시..

Win32 COM에 맞춰 빌드 속성에서 하위버전으로 맞춰 컴파일을 다시하는 방법도 있지만 메인 프로젝트가 .NET이라면 참조되는 모든 프로젝트를 다 바꿔야할 노릇..

또 다른 방법은 COM+를 이용하여 독립적으로 만드는 것이다.
분리시키는 방법은 아래 주소해서 확인할 수 있다.

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






 

Posted by 리본매냐

x64 환경 : .NET + COM 프로젝트 실행시 오류 - 80040154


x86 운영체제와는 달리, x64 환경으로 이전해 오면서 이런 문제도 발생하게 되는 군요.

솔루션에 Win32 COM 프로젝트와 .NET 프로젝트를 두고 테스트를 하였습니다. Win32 COM 프로젝트는 기본 구현에서 새로운 ATL Simple Object 를 추가한 상태이고, 이를 .NET 프로젝트 측에서 참조한 후, 해당 COM 개체를 생성하려는 데 다음과 같은 오류가 발생하는 경우입니다.

vcpp_cs_mixed_error_1.PNG

"
An unhandled exception of type
'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll

Additional information: Retrieving the COM class factory for component with
CLSID {....} failed due to the following error: 80040154
"

원인은 간단합니다. Win32 VC++ 프로젝트 유형은 빌드시에 기계어로의 컴파일이 완료되는 반면, 닷넷 프로젝트는 실행시에 JIT 컴파일러에 의해서 대상 머신에 최적화된 기계어로 변환되기 때문입니다.

감이 오시죠? ^^

Win32 VC++ 프로젝트는 다음과 같이 기본값이 "X86" 으로 지정되어 있습니다.

vcpp_cs_mixed_error_2.PNG

닷넷 프로젝트는 여러분들도 잘 아시는 것처럼 "Any CPU"로 지정되어 있습니다.

vcpp_cs_mixed_error_3.PNG

결과적으로, ConsoleApplication1 응용 프로그램은 실행시에 대상 머신의 환경에 맞게 64비트 응용 프로그램으로 구동되는 반면, 그 내부에서 생성되는 COM DLL 은 32비트로 컴파일 되어 있어 로드시에 오류가 발생하게 되는 것입니다.

그렇다면, 해결 방법은?
어쩔 수 없지요. 어느 한쪽에서 맞춰주는 수 밖에는. 닷넷에서 "Any CPU" 값을 "x86" 으로 바꿔주거나, COM DLL 프로젝트에서 "X64" 로 바꿔주어야 합니다.

Posted by 리본매냐
http://dalbong2.net/trackback/72 에서 퍼옴

메모리 관리를 설명하는 부분을 보면 항상 나오는 말들인데도, 처음 개발에 들어선 개발자들에겐 돌아서면 헛갈리는 부분이다. 이 포스트에서는 이것들의 차이점을 정리해 본다. 

■ null !

이것의 의미는 분명하다. 메모리상에 존재하는 객체에 대한 모든 참조의 끈을 끊는다는 의미이다. 만약 메모리상의 객체를 참조하는 변수가 모두 null로 되면 메모리상의 객체는 가비지 컬렉트 (Garbage Collect)후보가 된다. 이때 가비지 컬렉팅이 일어나면 해제된다.

null의 원래 의미는 이렇지만, .NET 프레임워크에서는 디버깅모드와 릴리스 모드( + 최적화모드)에 따라서 다르게 해석할 수 있다. 다음 코드를 보자.

[STAThread]

static void Main()

{

    Timer t = new Timer();



    // 필요한 작업을 한다.


    Console.Read();


    t = null;

}

필요한 작업을 하고 코드는 사용자로부터 키 입력을 기다릴것이다. Main 메소드가 호출될때 이 메소드는 컴파일(JIT 컴파일)되고 Timer 객체 t가 메모리에 생성될 것이다. 그러나 Timer 객체를 참조하는 t에 null을 설정함으로써 이제 이 객체를 가리키는 참조가 하나도 없게 된다. 만약 최적화 옵션(그런 것이 있단다-_-;;)이 활성화된 상태의 JIT 컴파일러가 컴파일을 하게 되면 이 경우 Timer객체를 참조하는 변수가 하나도 없다고 판단한다.

그래서 사용자로부터 키 입력을 기다리고 있는 동안 가비지 컬렉팅이 수행되면  이 Timer 객체는 가비지 컬렉션의 후보가 될 것이다.  메소드가 아직 실행중이라는 것은 객체의 가비지 컬렉팅을 막아주지 못한다는 사실을 염두에 둘 필요가 있다.

그러나 디버깅 모드에서는 메소드(여기서는 Main)도 하나의 가상 참조(참조 그래프상의 "Root"노드가 되는 것이다)로 여긴다. 무슨 말인가 하면 Main 메소드라는 참조가 Timer 객체를 참조하고 있다고 해석하는 것이다. 결과적으로 디버깅모드에서는 가비지 컬렉팅이 일어나도 Timer객체는 살아남게 되는 것이다.

그러나 어플리케이션이 디버깅 모드에서는 잘 돌아가다가 릴리스 모드에서는 에러가 발생한다면 난처한 일이 아닐 수 없다. 이것을 해결하는 방법으로 객체를 해제할때 null대신에 Dispose 메소드를 사용하면 된다.

■ Finalize 메소드

.NET에서 Finalize 메소드는 일반 메소드와 달리 클래스명 앞에 틸드(~)가 붙어서 "~클래스명() "형태를 갖는 메소드를 말한다. 어떤 타입에 대해서 Finalize 메소드를 정의해놓게 되면 가비지 컬렉팅 작업에 의해서 객체가 수거되려고 할때 GC는 그 타입의 Finalize 메소드를 호출해서 정의된 메모리 해제 작업을 수행한다.

■ Dispose 메소드

Finalize 메소드는 GC가 호출하는 메소드인 반면에 Dispose 메소드는 객체의 클라이언트가 직접 호출할 수 있는 메소드이다. null은 객체의 메모리 해제 시기를 결정할 수 없다. GC(Garbage Collector)가 컬렉팅을 수행할때까지 메모리에 남게 된다. 해서 객체를 사용하는 클라이언트측에서 직접 객체가 차지하는 자원을 해제할 수 있는 방법을 제공해줄 수 있는 방법이 Dispose 메소드이다. 앞의 코드를 Dispose()를 이용해서 변경하면 다음과 같다.

[STAThread]

static void Main()

{

    Timer t = new Timer();



    // 필요한 작업을 한다.


    Console.Read();

    t.Dispose(); // t = null;

}

이런 식으로 코딩을 하면 디버깅 모드이든, 최적화된 릴리스 모드이간에 Timer 객체에 대한 참조가 여전히 유효하게 되어 Timer 객체는 가비지 대상이 되지 않는다.  (-> Dangling Reference??)

■ Dispose 패턴

IDisposable 인터페이스를 구현하는 .NET 프레임워크 제공의 모든 객체들은 Dispose() 메소드를 호출해서 클라이언트가 직접 원하는 시기에 해제할 수 있도록 하고 있다. 만약 Dispose()를 지원하는 타입을 사용자가 직접 정의한다면 Dispose()에서 자원을 해제하는 코드를 원하는 대로 넣으면 된다.

Dispose()를 직접 정의할때 주의할 점은 클라이언트가 직접 Dispose()를 호출해서 자원을 해제했다면 그 자원 해제 사실을 GC가 알 수 있도록 표시를 해 줘야 한다. 그래야  이미 해제 했던 자원을 GC가 또 해제하지 않을 수 있게 된다. 만약 또 해제하려고 한다면 에러가 발생한다. 따라서 Dispose 패턴 이라는 것이 나오게 된다. 이 패턴은 객체의 클라이언트와 GC가 자원 해제를 중복되게 시도하지 않고 안전하게 자원을 해제할 수 있는 코딩 패턴을 말해준다. 실제 Dispose 코딩 패턴에 대해서는 "dipose pattern"이라는 검색어로 구글링해보면 자세히 알아 볼 수 있을 것이다.

Posted by 리본매냐

닷넷 설치버전 확인하기
지정된
레지스트리 값을 검색하여 .NET Framework 컴퓨터에 설치되어 있는지 여부를 확인할 있습니다. 다음 표에는 특정 버전의 .NET Framework 설치되어 있는지 여부를 테스트할 있는 레지스트리 목록이 정리되어 있습니다.

버전

레지스트리 이름

3.0

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0\Setup

InstallSuccess (DWORD value = 1)

2.0

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727

Install (DWORD value = 1)

1.1

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v1.1.4322

Install (DWORD value = 1)

1.0

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\policy\v1.0

3705 (REG_SZ value = 3321-3705)

참고 .NET Framework 1.0 1.1 대해 이전에 릴리스된 서비스 팩을 검색하는 방법은 Microsoft 기술 자료 문서 318785, "설치된 .NET Framework 버전 서비스 팩이 적용되었는지 여부를 확인하는 방법" 참조하십시오.



http://msdn.microsoft.com/ko-kr/library/aa480198.aspx 에서 자세한 내용을 확인할 수 있습니다.

Posted by 리본매냐
멀쩡하게 잘 돌아가던 VS2008 프로젝트가 갑자기 빌드시 이런 오류 메세지를 뱉(?)었다.
Win32 매니페스트를 포함하는 동안 오류가 발생했습니다. <file> 매니페스트 파일을 찾을 수 없습니다.

이 오류를 해결하려면

  • /win32manifest 컴파일러 옵션에 올바른 파일 이름과 경로를 지정합니다.

Posted by 리본매냐

최근에 달린 댓글

최근에 받은 트랙백

글 보관함