'Programmings/Windows Programming'에 해당되는 글 35건

  1. 2009.05.18 GetWindowThreadProcessId()
  2. 2009.05.15 GetModuleFileNameEx()
  3. 2009.04.27 DllMain
  4. 2009.04.24 DLL 제작 (Explicit)
  5. 2009.04.23 DLL 제작 (Implicit 연결)
  6. 2009.04.23 DLL 이란...
  7. 2009.03.03 아스키 코드표
  8. 2009.02.05 프로그램 실행 에러 - MFC71D.DLL을(를) 찾을 수 없으므로... 5
  9. 2009.01.19 MFC42D.DLL 을 찾을 수 없다라는 메시지 창이 뜰 때.. 22
  10. 2008.10.01 Windows API 메시지 데드록(DeadLock) 관련 함수 1
2009. 5. 18. 11:38

GetWindowThreadProcessId()



GetWindowThreadProcessId() 함수는 HWND 값을 이용하여 프로세스 ID를 알려주는 함수이다.

DWORD GetWindowThreadProcessId (
                                                      HWND       hWnd;
                                                      LPDWORD lpdwProcessId
                                                      );
hWnd              - PID를 얻고자 하는 윈도우의 핸들
lpdwProcessId - 반환받을 PID의 포인터, NULL로 설정할 경우 PID는 리턴값으로 반환된다.

이 함수를 사용하기 위해서는 user32.dll과 user32.lib 를 필요로 한다. 하지만 이들은 기본적으로 VS2005로 작업할 때 포함되어 있으므로 구지 신경을 쓸 필요는 없다.

예)
DWORD pid;
GetWindowThreadProcessId(hWnd, &pid);
// 또는
pid = GetWindowThreadProcessId(hWnd, NULL);




'Programmings > Windows Programming' 카테고리의 다른 글

다른 윈도우에서의 GetFocus() 사용하기  (0) 2009.05.28
서브클래싱  (0) 2009.05.26
GetModuleFileNameEx()  (0) 2009.05.15
DllMain  (0) 2009.04.27
DLL 제작 (Explicit)  (0) 2009.04.24
2009. 5. 15. 18:14

GetModuleFileNameEx()



GetModuleFileNameEx() 함수는 현재 실행된 다른 프로그램의 실팽파일의 경로를 얻을 수 있는 함수이다.

DWORD WINAPI GetModuleFileNameEx( __in HANDLE hProcess,
                                                          __in_opt  HMODULE hModule,
                                                          __out LPTSTR lpFilename,
                                                          __in DWORD nSize
                                                         );
hProcess - 원하는 모듈을 가지고 있는 프로세스의 핸들.
hModule - NULL로 설정을 하여 실행중인 파일의 경로를 받아올수 있게 한다.
lpFilename - 실행되는 모듈의 경로를 받아올 버퍼.
nSize - 실행되는 파일의 경로를 가져올 버퍼의 크기.

ex) GetModuleFileNameEx(hProc, NULL, str, lstrlen(str));
이 함수를 사용하기 위해서는 'Psapi.h'라는 헤더파일을 포함해 주어야 한고, psapi.lib 파일을 추가해주어야 한다.
아래는 '팁소프트'의 게시판에서 가져온 자료이다.
// GetModuleFileNameEx 함수를 이용하여 경로를 얻기위한 함수
// 프로세스의 경로를 얻기 위해서는 프로세스 정보에 접근해야 하는데, 프로세스의 정보에 접근하기 위해선 해당
// 프로세스의 아이디가 필요하다.
// 프로세스 아이디는 해당 프로세스와 연결된 윈도우 핸들을 통해 알 수 있으며 원하는 프로그램의 윈도우핸들은
// FindWindow 또는 FindWindowEx 함수를 이용해서
찾을 수 있다.
//
// [ 프로세스 정보에 접근하는 순서 ]
// 1. FindWindow 함수로 원하는 프로세스의 윈도우 핸들을 찾는다.
// 2. 윈도우 핸들을 이용하여 프로세스 아이디를 구한다.
// 3. 프로세스 아이디를 이요아여 프로세스 정보를 오픈한다.
void 클래스명::GetExecuteFileName()
{
    // "Test"라는 이름을 가진 윈도우를 찾는다.
    HWND h_wnd = ::FindWindow(NULL, "Test");
    unsigned long process_id = 0;
    // 윈도우 핸들을 이용하여 프로세스 아이디를 구한다.
    GetWindowThreadProcessId(h_wnd, &process_id);
    char temp[256] = {0,};

    // 프로세스 아이디를 이용하여 해당 프로세스 핸들 값을 얻는다.
    HANDLE hwnd = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_id);
    if(hwnd != NULL){
        // 정상적으로 프로세스를 열었다면 프로세스의 경로명을 얻는다.       
        // 정상적으로 경로명을 얻었다면 해당 경로명을 그렇지 못했다면 파일명만을 출력한다.
        if(GetModuleFileNameEx(hwnd, NULL, temp, 256)) MessageBox(temp);
    }
}

더 많은 내용은 '팁소프트'에 방문하면 찾을 수 있을 듯 한데.. ^^; 광고 아님.. ㅎ

'Programmings > Windows Programming' 카테고리의 다른 글

서브클래싱  (0) 2009.05.26
GetWindowThreadProcessId()  (0) 2009.05.18
DllMain  (0) 2009.04.27
DLL 제작 (Explicit)  (0) 2009.04.24
DLL 제작 (Implicit 연결)  (0) 2009.04.23
2009. 4. 27. 11:43

DllMain



DLL은 함수들의 집합이므로 함수에 대한 정의만 있으면 되고 일반적인 실행파일의 WinMain과 같은 메인함수가 꼭 있어야 하는것은 아니다. 엄밀히 말하자면 DLL도 반드시 Main이라는 엔트리포인트가 필요하지만, VC++를 사용할 경우 C런타임이 엔트리 포인트를 대신 제공하기 때문에 없어도 상관이 없다는 것이다.

DLL이 단순한 함수의 집합이 아니라면 DLL의 엔트리 포인트 DllMain이 필요하다. 전역변수가 있다거나 동적으로 메모리를 할당해 사용한다거나 할 때 초기화와 종료 처리를 위해 필요하다.

BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID lpRes);

hInst는 DLL의 인스턴스 핸들이다.
fdwReason은 이 함수가 호출된 이유를 지정한다.(일종의 통지 메시지)
  DLL_PROCESS_ATTACH
  - DLL이 프로세스의 주소공간에 맵핑될 때 호출된다.
    주로 메모리를 할당하거나 시스템 전역 핸들을 초기화하는 용도로 사용된다.
  DLL_PROCESS_DETACH
  - DLL이 프로세스의 주소 공간에서 분리될 때 호출된다.
    할당한 메모리를 해제하거나 시스템 전역 핸들을 파괴하는 용도로 사용된다.
  DLL_THREAD_ATTACH
  - DLL을 사용하는 프로세스에서 스레드를 생성할 때마다 이 값과 함께 DllMain함수가 호출된다.
    DLL에서는 이 값을 받았을 때 스레드별 초기화를 수행한다.
  DLL_THREAD_DETACH
  - DLL을 사용하는 프로세스에서 스레드가 종료될 때마다 이 값과 함께 DllMain 함수가 호출된다.
    DLL에서는 이 값을 받았을 때 스레드별 종료 처리를 한다.
lpRes는 DLL의 연결 방식을 지정한다.
  TRUE - 암시적 연결
  FALSE - 명시적 연결

BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID lpRes)
{
    switch(fdwReason) {
        case DLL_PROCESS_ATTACH:
            ...
            break;

        case DLL_PROCESS_DETACH:
            ...
            break;

        case DLL_THREAD_ATTACH:           
            ...
            break;

        case DLL_THREAD_DETACH:
            ...
            break;
    }
    return TRUE;
}

이런 식으로 구현을 해주면 된다.
해당하는 통지 메시지가 전달 될 때 필요한 작업을 넣어준다. 가만히 보고 있자면 하는 일이 WndProc와 비슷한것 같다면서.. ^^;


'Programmings > Windows Programming' 카테고리의 다른 글

GetWindowThreadProcessId()  (0) 2009.05.18
GetModuleFileNameEx()  (0) 2009.05.15
DLL 제작 (Explicit)  (0) 2009.04.24
DLL 제작 (Implicit 연결)  (0) 2009.04.23
DLL 이란...  (0) 2009.04.23
2009. 4. 24. 15:02

DLL 제작 (Explicit)



DLL을 명시적(Explicit)으로 연결하기 위한 방법이다.
명시적(Explicit) 연결이라는 부분에 대해서는 프로그램이 실행되고 있는 도중에 필요한 함수가 포함된 DLL을 로드하는 방식이라고 보면 될 듯하다.

명시적인 연결을 위한 DLL을 제작할 때 중요한 함수들이 있다.
HINSTANCE LoadLibrary(LPCTSTR lpLibFileName);
지정한 DLL을 메모리로 읽어와 현재 프로세스의 주소공간에 맵핑시켜 사용할 수 있도록 한다. 하지만, 이미 다른 프로세스에서 해당 DLL을 사용하고 있다면, DLL을 메모리로 또다시 올리는 것이 아니고 DLL 의 사용 카운트만 1 증가시킨다.
인수는 읽고자 하는 DLL 의 파일 이름이다. 파일의 경로를 지정할 수도 있고, 지정하지 않을 수도 있다. 파일의 경로를 지정하지 않으면 DLL을 찾는 순서에 따라 경로를 뒤져가며 해당 DLL을 찾게 된다.

FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
DLL에서 엑스포트한 함수의 번지를 찾아 그 함수의 함수 포인터를 리턴한다.
첫 번째 인수는 함수가 포함된 DLL의 모듈 핸들이며 LoadLibrary() 가 리턴한 값이다.
두 번째 인수는 찾고자 하는 함수 이름이다.
이 함수가 리턴한 함수포인터를 사용하여 DLL에 있는 함수를 호출한다.

BOOL FreeLibrary(HMODULE hLibModule);
DLL의 사용 카운트를 1 감소시키며 사용 카운트가 0이 되었을 경우 메모리에서 DLL을 삭제한다.
첫 번째 인수는 LoadLibrary()가 리턴한 DLL의 모듈 핸들이다. LoadLibrary()로 DLL을 읽어왔다면 반드시 프로세스를 종료하기 전에 FreeLibrary()를 호출하여 DLL을 해제해야 한다.


DLL 제작
DLL 제작 방법은 아래를 참조하면 될듯.. -_-;;
http://todayis.tistory.com/206

DLL Test 프로그램(명시적 연결) 제작
새로운 Win32 프로젝트를 생성하고, WndProc 소스 부분을 아래와 같이 굵은 글자로 된 부분을 추가한다.
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    HINSTANCE hInst;
    int(*pFunc)(int, int);
    TCHAR str[128];

    switch (iMessage) {
    case WM_CREATE:
        hWndMain=hWnd;
        return 0;
    case WM_PAINT:
        hdc=BeginPaint(hWnd, &ps);
        hInst = LoadLibrary(L"DLL_test.dll");
        pFunc = (int(*)(int, int))GetProcAddress(hInst, "AddInteger");
        wsprintf(str, L"1+2 = %d", (*pFunc)(1, 2));
        TextOut(hdc, 10, 10, str, lstrlen(str));
        FreeLibrary(hInst);
        EndPaint(hWnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

컴파일.. 하고 실행을 하면.. 전에 설명했던 암시적(Implicit) 연결과 동일한 결과임을 알 수 있다.

단지 명시적 연결의 경우 원하는 위치에서 DLL을 직접 호출하는 구문이 있다는 것이다. 위의 경우에는 WM_PAINT
DLL을 사용하는 프로그램이 실행될 때 DLL이 같이 로드되는 것이 아니기 때문에 Settings에 따로 XXX.lib를 지정할 필요가 없다. 또 함수포인터로 함수가 있는 번지를 직접 조사한 후 그 주소를 이용하기 때문에 함수의 원형같은 것도 필요가 없다.
어떻게 보면, 명시적인 연결을 사용하는 DLL 이 더 쉬운듯 하다.

추가로 에러를 위한 처리구문을 추가하자.
LoadLibrary() 그리고 GetProcAddress() 등의 함수를 사용하는 부분을 아래와 같이 처리해 주면 된다.
if((hInst = LoadLibrary(L"DLL_test.dll")) == NULL) {
    MessageBox("There are no DLLs!!!");
    // 추가적인 에러 처리
    return 0;
}
if((pFunc = (int(*)(int, int))GetProcAddress(hInst, "AddInteger")) == NULL) {
    MessageBox("Where is The Function what I want to?? ");
    // 추가적인 에러처리
    return 0;
}


명시적(Explicit) 연결의 장점
1. 필요할 때만 DLL을 읽어와 사용하므로 메모리와 리소스가 절약된다.
2. 상황에 따라 사용할 DLL을 교체할 수 있다.
3. 필요한 DLL이 없는 경우라도 프로그램을 실행할 수는 있다. DLL을 사용하는 부분에서는 정상적인 동작을 안하더라도...
4. DLL을 호출하는 프로그램의 시작 실행속도가 빠르다.

명시적(Explicit) 연결의 단점
1. 사용하기 전에 DLL을 메모리로 읽어오므로 함수 호출 속도가 느리다.

  • 윈도우즈 API 완전정복 참고...


'Programmings > Windows Programming' 카테고리의 다른 글

GetModuleFileNameEx()  (0) 2009.05.15
DllMain  (0) 2009.04.27
DLL 제작 (Implicit 연결)  (0) 2009.04.23
DLL 이란...  (0) 2009.04.23
아스키 코드표  (0) 2009.03.03
2009. 4. 23. 22:17

DLL 제작 (Implicit 연결)



DLL 제작
단순히 DLL 파일을 생성하는 방법이다. DLL은 단독으로 실행될 수 없으므로 이 파일을 가지고 테스트를 할 수는 없다.(테스트 프로그램을 따로 제작할 것이다.)

1. Visual Studio를 실행한다.(본인의 경우 Visual Studio 2005 임)
2. File -> New -> Project..
3. New Project 위자드
   - Visual C++ 탭에서 Win32를 선택하고, 템플릿으론 Win32 Project를 선택한다.
   - Name, Location, Solution Name는 알아서 대충 넣어준다..
4. 대충 Next 버튼을 클릭하며, Application Settings에서는  DLL을 선택한다.
5. Finish 버튼 클릭!!
6. 새프로젝트가 만들어지면, .cpp파일을 하나 생성하고, 테스트용으로 간단한 내용을 입력한다.
// 윈도우즈 API 완전정복의 코드임..
// a, b를 입력받아 a, b의 합을 리턴하는 코드임
// 다른 프로그램에서 이 함수를 사용할 수 있도록 extern "C"__declspec를 사용..
extern "C"__declspec(dllexport) int AddInteger(int a, int b)
{
    return a+b;
}

7. 이 프로젝트를 컴파일하면 해당하는 .dll과 .lib 파일이 생성된다.


DLL 테스트 프로그램 제작
Implicit(암시적), Explicit(묵시적) 연결을 사용할 수 있다.

Implicit(암시적) 연결
MyDllTest라는 API 프로젝트를 만들고 다래 코드를 추가한다.

// DLL  함수를 위해 추가해야 하는 부분..
extern "C"__declspec(dllimport) int AddInteger(int, int);
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    TCHAR str[128];

    switch (iMessage) {
    case WM_CREATE:
        hWndMain=hWnd;
        return 0;
    case WM_PAINT:
        hdc=BeginPaint(hWnd, &ps);
        wsprintf(str, "1+2 = %d", AddInteger(1, 2));
        TextOut(hdc, 10, 10, str, lstrlen(str));
        EndPaint(hWnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
       return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}


다음은 사용하고자 하는 DLL의 임포트 라이브러리를 프로젝트에 포함시키는 작업을 해주어야 한다.
메뉴 탭의 Project -> XXXProperties.. (이미지 클릭 하셈!!! ㅋ)


마지막으로 .DLL 파일과 .lib 파일을 MyDllTest 프로젝트 디렉토리로 복사한다.
참고로 .DLL과 .lib 파일은 위에서 DLL 제작의 컴파일 결과물로 생성된 녀석들이다.


이 방법 말고도, DLL을 사용하려는 소스의 윗부분에 #pragma 문을 사용할 수도 있다.
#pragma comment(lib,"XXXDLL.lib") 를 추가하면 된다.
#pragma 지시자를 사용하면 컴파일러의 라이브러리 관리 모듈에게 XXXDLL.lib를 검색하도록 하게 하므로 위의 과정에서 보인것과 같은 설정 대화상자나 파일(.dll, .lib) 추가 없이 소스에서 곧바로 임포트 라이브러리를 지정할 수 있다.


그리고 컴파일... 후 실행하면..



추가로  DLL의 헤더파일을 정의해서 깔끔하게 DLL을 작성하는 방법이다.

위와 같이 함수의 내용이 얼마 되지 않는다면 그냥 사용할 수 있겠지만, DLL에 추가되는 함수의 수가 많아지게 되면, 선언의 꺼리(extern "C"__declspec..와 같은)가 그만큼 많아질 것이다.
헤더파일을 하나 만들어 선언을 모두 옮겨 놓는 방법도 하나의 해결 방안이 될 듯..

DLL의 프로젝트에 헤더파일 하나를 만든다.
그리고 아래와 같은 내용을 추가한다.

//XXX.h

#ifdef DLLEXPORT
#define MYDLLTYPE __declspec(dllexport)
#else
#define MYDLLTYPE __declspec(dllimport)
#endif

extern "C" MYDLLTYPE int AddInteger(int a, int b);

추가로 DLL에 함수를 추가하고자 한다면, 함수의 선언 부분을 extern "C" .. 의 아래에 추가시켜주면 될 것이다.

DLL의 .cpp 파일을 열어서 다음의 두줄을 추가한다.

#define DLLEXPORT             // DLL Export임을 선언(??)
#include "XXX.h"

이 두줄을 추가시키므로 인해서, DLL은 export 하는 용도임을 정의한다.

테스트 프로그램은 단지 XXX.h파일을 추가시켜준다.
어떠한 정의가 따로 되어있지 않으므로, __declspec(dllimport)로 인식할 것이다.


여기까지!!

이게 DLL을 사용하는 가장 간편한 방법이라고 하는데..
다른 방법들은.. 다음 이시간에.. !!!


'Programmings > Windows Programming' 카테고리의 다른 글

DllMain  (0) 2009.04.27
DLL 제작 (Explicit)  (0) 2009.04.24
DLL 이란...  (0) 2009.04.23
아스키 코드표  (0) 2009.03.03
프로그램 실행 에러 - MFC71D.DLL을(를) 찾을 수 없으므로...  (5) 2009.02.05
2009. 4. 23. 18:30

DLL 이란...



DLL(Dynamic Link)라는 것.. 동적 링크라고도 하는 이넘은... 컴파일시 함수의 코드가 실행 파일에 그대로 복사되는 것이아니고, 실행되는 파일이 실행 될 때 필요로 하는 함수가 실행 파일에 연결되는 형식이다. 실행파일은 단지 호출할 함수의 정보만 포함되고 실제 함수코드는 복사되지 않기 때문에 실행 파일의 크기가 작아진다. 하지만 실행시킬 루틴이 필요하기 때문에 실행파일은 실행시킬 함수에 대한 정보를 가지고 있어야하고, 실행시킬 함수는 DLL 파일의 형태로 존재하게 된다.

장점
1. 한 코드를 여러 프로그램이 같이 사용하기 때문에 메모리가 절약된다.
2. DLL을 사용하는 프로그램은 실행파일 자체에 해당 함수가 포함되지 않기에 크기가 작다.
3. 함수의 루틴을 바꾸고자(업그레이드) 할 경우 해당하는 DLL만 수정하면 된다.
...
이외에도 많은 장점들이 있는듯함..

단점
1. DLL 없이 실행프로그램 자체만으론 동작을 안한다. -_-;
2. DLL 이 교체되거나 하면, 프로그램이 정상동작을 안할 수도 있다.
... 등등..

DLL 연결 방법
1. 암시적(Implicit) 연결

함수가 어느  DLL에 있는지 밝히지 않고 그냥 사용을 하는 방법이다. DLL을 사용하려는 프로젝트는 해당 dll과 lib를 포함하고 있어야 하고, 윈도우즈는 임포트 라이브러리의 정보를 참조해서 해당 DLL을 로드하고 함수를 찾게 된다.
프로그램이 실행될 때 DLL이 로드되므로 실행시 연결(Load time Linking)이라고 한다.
2. 명시적(Explicit) 연결
어느 DLL에 있는 함수인지를 밝히고 사용하는 방법이다. 프로그램이 실행될 때 DLL이 로드되는 것이 아니라 로드하라는 명령이 있을 때만 해당 DLL이 로드된다. 함수가 속해있는 DLL의 이름을 명시적으로 지정하여 호출하므로 임포트 라이브러리는 필요하지 않다.
프로그램이 실행 중에 DLL이 메모리로 읽혀지기 때문에 실행중 연결(Run Time Linking)이라고 한다.

2009. 3. 3. 14:59

아스키 코드표



문자열 작업을 하다 보면 가끔 필요할 때가 있는데.. 그때마다 웹에서 아스키 코드 검색하는것두 꽤 귀찮다.
그냥 여기에 올려놓고 필요할 때 볼려구... ^^;

아스키 코드표

2009. 2. 5. 10:14

프로그램 실행 에러 - MFC71D.DLL을(를) 찾을 수 없으므로...



프로그램을 실행하다보면 간혹 다음과 같은 에러 메시지를 볼 때가 있다.
"MFC71D.DLL을(를) 찾을 수 없으므로 응용 프로그램을 시작하지 못했습니다. 이문제를 해결하려면 응용 프로그램을 다시 설치하십시오.

이는 MFC로 작성된 프로그램을 실행 시킬 때 필요로 하는 MFC71D.DLL이라는 파일이 없어서 발생하는 문제이다.이 때는 단순히 MFC71D.DLL 이라는 파일을 구해서 실행하는 파일이 있는 폴더 혹은 WINDOWS(C:\WINDOWS)폴더 혹은 System(C:\WINDOWS\System32)폴더에 복사한 후 해당 프로그램을 실행하면 된다.

위와 같이 다양한 경로에 MFC71D.DLL 파일을 넣어도 정상적으로 동작하는 이유는 해당 프로그램이 실행될 때 연관된 파일을 찾는 순서가 정해져 있어서 여기 저기 필요한 곳을 뒤져 필요한 파일을 찾아서 실행하기 때문이다.
  1. 프로그램의 실행파일이 존재하는 디렉토리
  2. Windows System(C:\WINDOWS\System32) 디렉토리
  3. Windows(C:\WINDOWS) 디렉토리
  4. 환경변수 PATH에 의해 지정된 디렉토리
MFC71D.DLL 파일을 넣은 뒤 응용 프로그램을 다시 실행하면 한번 더 에러 메시지를 볼 수 있다.
"MSVCR71D.DLL을(를) 찾을 수 없으므로 응용 프로그램을 시작하지 못했습니다. 이 문제를 해결하려면 응용 프로그램을 다시 설치하십시오."

이녀석도 마찬가지로 MSVCR71D.DLL을 MFC71D.DLL과 같은 방식으로 해주면 해결을 할 수가 있다.

이렇게 하고 다시 프로그램을 실행시키면 정상적으로 프로그램이 실행되는 것을 확인할 수 있을 것이다.

2009. 1. 19. 19:00

MFC42D.DLL 을 찾을 수 없다라는 메시지 창이 뜰 때..



가끔 MFC 응용 프로그램을 실행하다 보면 "MFC42D.DLL을(를) 찾을 수 없으므로 응용 프로그램을 시작하지 못했습니다. 이 문제를 해결하려면 응용 프로그램을 다시 설치하십시오"라는 메시지 창을 볼 기회가 있다.

아무래도 실행시키는 컴퓨터에 MFC 관련 라이브러리가 없어서 그러는 모양인지..
일반적인 릴리즈 버전의 MFC 프로그램의 경우 윈도우 설치시 설치가 되지만, 디버그용으로 배포된 MFC 프로그램을 실행할 경우 몇몇 라이브러리가 없어서 실행이 되질 않는 경우가 있다고 한다.
본인 컴퓨터에는 Visual Studio 2005가 설치된 상황인데.. Visual Studio 6.0 관련 라이브러리인가? -_-;;
VS 6.0으로 제작된 MFC 프로그램을 실행할 때 발생했던 메시지 창이라서.... ^^;

일단 이리 저리 자료를 찾다가 몇몇 필요한 파일이있다는 것을 알아버렸다!!
  • MFC42D.DLL
  • MFCO42D.DLL
  • MSVCRTD.DLL
  • MSVCP60D.DLL

이녀석을을 구해서 C:\WINDOWS 폴더 혹은 C:\WINDOWS\system32 폴더에 복사를 해주면 정상적으로 프로그램이 실행된다.

검색을 해보면 이리저리 쉽게 구할 수 있는 파일들이지만.. 혹시나 구하기 힘들다거나 검색했는데 이 페이지가 검색된 사람은 아래 압축파일을 사용해도 무관하지만.. 그래도 의심이 많은 사람은 안써도 상관 없음!! ㅋ


2008. 10. 1. 18:02

Windows API 메시지 데드록(DeadLock) 관련 함수


'SendMessage()'라는 함수를 통해서 프로그래머는 일종의 사용자 메시지를만들 수 있다.
같은 스레드 내에서 이 함수를 사용할 경우에는 크게 문제 될 것이 없지만, 다른 스레드로 SendMessage()를 사용해 메시지를 날리게 될 경우 상당히 좋지않은 결과를 초래할 수도 있다.

SendMessage() 함수는 메시지를 받은 윈도우 프로시저가 리턴하기 전까지는 리턴하지 않기 때문에, 다른 스레드로 메시지를 날리게 될 경우 그 스레드에서 리턴하지 않는 한 SendMessage()를 한 스레드는 홀드되는 상태로 남게 된다. '데드록(DeadLock)'가 되는 것이다.

이를 해결하는 방법으로 여러가지가 있겠지만, 간단히 몇가지를 살펴보면 다음과 같다.
'InSendMessage()''ReplyMessage()'를 이용하여 SendMessage()로 부터 받은 메시지를 처리하는 부분이다.
if(InSendMessage())             // 다른 스레드로부터 메시지가 들어왔는지 확인
    ReplyMessage(TRUE);      // SendMessage() 로부터 전달된 메시지를 바로 리턴한다.

위와 같은 처리를 해주면, SendMessage()를 호출한 윈도우는 리턴되지 않더라도 즉시 다른 일을 할 수 있다.

다른 방법으로는 SendMessage()를 이용하지 않고 다음의 함수를 사용하는 방법이다.
BOOL SendNotifyMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
LRESULT SendMessageTimeout( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam,              
                                                UINT fuFlags, UINT uTimeout, PDWORD_PTR lpdwResult );

'SendNotifyMessage()' 함수는 SendMessage()와 유사하지만, hWnd 가 다른 스레드의 윈도우일 경우 대기를 하지 않고 즉시 리턴하는 함수이다.
'SendMessageTimeout()' 함수는 지정한 시간이 지나면 메시지의 처리 여부와 상관없이 즉시 리턴함으로 메시지를 보낸 윈도우가 홀드되는 것을 막는다.