2016년 4월 11일 월요일

[미완] 프로그램 설치시 사용할 수 없는 드라이브 에러 발생

[미완] 프로그램 설치시 사용할 수 없는 드라이브 에러 발생


인스톨쉴드(InstallShield)로 만들때 프로그램 설치위치를 설정 안하면
레지스트리에 저장된 위치에 프로그램을 설치한다.

이때 레지스트리의 저장 위치가 사용할 수 없는 드라이브이면 위와 같은 에러를 출력한다.

레지스트리 실행(실행창에 regedit 입력)

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
(64bit OS는 밑에도 확인)
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders

위 이미지 처럼 C드라이브 인지 확인 한다.

2016년 3월 25일 금요일

[미완] [C/C++] [Book] C++ 템플릿 가이드

[미완] [C/C++] [Book] C++ 템플릿 가이드

저자: 데이비드 반데보드
역자 한정해
출판사 에이콘

수준: 중급
선행학습: C++

기억에 남는것: 템플릿은 .h에 선언과 구현을 다 해라

C++ 템플릿의 관한 유일한 책인것 같다.

저는 코딩시 Template를 사용(=구현)하지 않습니다.
Template를 단순하게 얘기하면 데이터형 별로(int, double, ...) 함수, Class를
만들지 말고 Template 하나로 만들면 된다데
저는 그냥 데이터별로 만듭니다.
왜냐하면 저는 라이브러리를 만드는게 아니고 UI이다보니
제가 Template를 사용해서 구현할 일은 적고 가독성만 떨어져서요.
대신 남이 만들어놓은 Template(STL)들은 사용합니다.
어떻게 보면 사용법만 알고 있는 수준입니다.

C++ Template Metaprogramming, Modern C++ Design 보기에 앞서서
선행학습으로 책을 봤지만
아직 수준이 낮아서 깊게 들어가면 이해가 안 간다.

크게 4 Part로 구성되어 있다.
1부는 기본적인 문법
2부는 템플릿 깊게
-> "이것 문법에러 안나나?" 생각이 들면서 슬슬 이해가 안되기 시작한다.
3부는 설계
-> 첫번째 다형성을 보면서 좋았다.
템플릿보다는 설계측면을 보게 되어서 좋았는데
이 이후부터는 이해가 안가기 시작한다.
4부는 실제 프로그램(?)인데
스마트포인터 빼고는 이해가 안간다.
(스마트포인터도 후반부에는 모름)

책을 끝까지 다 봤지만
나는 아직도 "특질"이라는 단어가 뭘 의미하는지 모르겠고
꼭 저 단어로 번역을 했어야 했나 싶다.

2016년 1월 5일 화요일

셜록: 유령신부 (Sherlock: The Abominable Bride, 2016)


개봉일: 2016.01.02 (토)
시청일: 2016.01.04 (월)

한줄평: 드라마 셜록팬들을 위한 영화(?)

 [ 줄거리 ]
19세기 빅토리아 시대에
자살한 신부가 나타나서 남편을 살해하는 사건이 발생하고
셜록이 수사를 한다.

[ 감상평 ]
드라마 셜록의 시즌3, 4 사이의 스페셜 드라마로
BBC에서 반영한 것을 우리나라에서는 극장에서 개봉했다.
그래서 드라마 셜록을 봐야 영화가 이해된다.

초반 빅토리아 시대의 이야기는 좋았는데
중반이후 현재(시즌3, 4 사이)와 연결되면서 별로다.

영화를 보기 위해서 드라마를 봐야 하지만
시즌4를 보기 위해서 영화를 볼 필요는 없다.

2015년 12월 9일 수요일

[미완] [책] 수수께끼 풀이는 저녁식사 후에

[미완] [책] 수수께끼 풀이는 저녁식사 후에

책은 좀 당황스럽다.
어떤 사건을 한권동안 풀줄 알았는데
6개의 사건이 나오는 단편이다.

보면서 만화책(김전일, 코난)이 생각났다.
사건이 발생하고 용의자들이 나오고
사건을 해결하고 끝

단편이라 당황했지만
부담없이 편하게 읽을수 있다.

2015년 12월 2일 수요일

[미완] 책 Windows 구조와 원리

[미완] 책 Windows 구조와 원리 : OS를 관통하는 프로그래밍의 원리
저자: 정덕영
출판사: 한빛미디어

별: 3개

책은 로우레벨에대해서 자세히 설명을 하고 있지만

책을 보는 내 수준이 안되어서 중간이후부터는 이해를 못하고 그냥 끝까지 읽었다.

나는 응용프로그램머라서 WinDBG는 쓸줄모르고 로우레벨딴 프로그램은 거의 안 짜바서 그렇고

시스템이나 드라이버 관련자들은
이 책은 많은 도움이 될것 같다.


* 나에게 시스템 관련 책은
윤성우 저자의 뇌를 자극하는 윈도우즈 시스템 프로그래밍이
맞는것 같다.

[미완] 리눅스 민트에서 코드블럭 컴파일시 에러

[미완] 리눅스 민트에서 코드블럭 컴파일시 에러

g++와 xterm 설치

g++: c++ 컴파일을 위해서
xterm: 터미널 실행을 위해서

2015년 11월 3일 화요일

[미완] [Win32/MFC] 작업관리자의 프로세스와 응용프로그램 추출

[미완] [Win32/MFC] 작업관리자의 프로세스와 응용프로그램 추출


위 그림에서 프로세스 이름(보라)와 타이틀명(빨강) 추출하는 법
프로세스 이름(보라)는 2가지가 있고 타이틀명(빨강)은 1개 올림
블로그로 보면 상당히 지저분한데 소스는 헤더파일로 분리해서 심플합니다.
단 VS6에서 잘 돌아가나 유니코드때문에 다른 버전은 수정을 해야 합니다.
(*지금은 그냥 올리고 나중에 유니코드로 수정해서 다시 올리 예정)

소스 다운로드
http://cfile218.uf.daum.net/attach/246D7D4A563822CF31088D

타이틀명(빨강) 추출
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <vdmdbg.h>
#include <tchar.h>
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    _TCHAR szTitle[MAX_PATH] = {0, };
    DWORD dwPID = 0;

    PROCESSENTRY32 pEntry;
    memset(&pEntry, 0x00, sizeof(PROCESSENTRY32));
    pEntry.dwSize = sizeof(pEntry);

    // process list(like taskmgr)
    DWORD exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
    BOOL isVisible = IsWindowVisible(hwnd);
    BOOL isToolWindow = (exStyle & WS_EX_TOOLWINDOW);
    BOOL isAppWindow = (exStyle & WS_EX_APPWINDOW);
    BOOL isOwned = GetWindow(hwnd, GW_OWNER) ? TRUE : FALSE;

    if (!(isVisible && (isAppWindow || (!isToolWindow && !isOwned))))
        return TRUE;

    GetWindowText(hwnd, szTitle, MAX_PATH); // get caption
    GetWindowThreadProcessId(hwnd, &dwPID);

    HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, dwPID);
    Process32First(hSnapShot, &pEntry);

    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID);

    while (!(dwPID == pEntry.th32ProcessID) && IsWindowVisible(hwnd))
    {
        if (FALSE == Process32Next(hSnapShot, &pEntry))
            break;
 
        hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID);
    }

    _TCHAR szRes[MAX_PATH] = {0, };
    _stprintf(szRes, _T("PID : 0x%08x, Title : %s, Filename : %s\n"), dwPID, szTitle, pEntry.szExeFile);
 _tprintf( szRes );

    return TRUE;
}

프로세스 이름(보라) 추출 방벙 1
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <vdmdbg.h>
#include <tchar.h>
BOOL ProcessList()
{
    HANDLE   hProcess = NULL;
    PROCESSENTRY32 ppe = {0};

    hProcess = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
    ppe.dwSize = sizeof( PROCESSENTRY32 );

    if( Process32First( hProcess, &ppe ) )
    {
        do
        {
            _tprintf(_T("%-30s (%d) \n"), ppe.szExeFile, ppe.th32ProcessID);
  
        } while ( Process32Next( hProcess, &ppe ) );
    }

    CloseHandle (hProcess);

    return TRUE;
}

프로세스 이름(보라) 추출 방벙 2
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <vdmdbg.h>
#include <tchar.h>
typedef BOOL (CALLBACK *PROCENUMPROC)(DWORD, WORD, LPSTR, LPARAM);
typedef struct {
   DWORD          dwPID;
   PROCENUMPROC   lpProc;
   DWORD          lParam;
   BOOL           bEnd;
} EnumInfoStruct;
BOOL WINAPI EnumProcs(PROCENUMPROC lpProc, LPARAM lParam);
BOOL WINAPI Enum16(DWORD dwThreadId, WORD hMod16, WORD hTask16,
      PSZ pszModName, PSZ pszFileName, LPARAM lpUserDefined);
//
// The EnumProcs function takes a pointer to a callback function
// that will be called once per process with the process filename
// and process ID.
//
// lpProc -- Address of callback routine.
//
// lParam -- A user-defined LPARAM value to be passed to
//           the callback routine.
//
// Callback function definition:
// BOOL CALLBACK Proc(DWORD dw, WORD w, LPCSTR lpstr, LPARAM lParam);
//
BOOL WINAPI EnumProcs(PROCENUMPROC lpProc, LPARAM lParam) {
   OSVERSIONINFO  osver;
   HINSTANCE      hInstLib  = NULL;
   HINSTANCE      hInstLib2 = NULL;
   HANDLE         hSnapShot = NULL;
   LPDWORD        lpdwPIDs  = NULL;
   PROCESSENTRY32 procentry;
   BOOL           bFlag;
   DWORD          dwSize;
   DWORD          dwSize2;
   DWORD          dwIndex;
   HMODULE        hMod;
   HANDLE         hProcess;
   char           szFileName[MAX_PATH];
   EnumInfoStruct sInfo;
   // ToolHelp Function Pointers.
   HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD, DWORD);
   BOOL (WINAPI *lpfProcess32First)(HANDLE, LPPROCESSENTRY32);
   BOOL (WINAPI *lpfProcess32Next)(HANDLE, LPPROCESSENTRY32);
   // PSAPI Function Pointers.
   BOOL (WINAPI *lpfEnumProcesses)(DWORD *, DWORD, DWORD *);
   BOOL (WINAPI *lpfEnumProcessModules)(HANDLE, HMODULE *, DWORD,
         LPDWORD);
   DWORD (WINAPI *lpfGetModuleBaseName)(HANDLE, HMODULE, LPTSTR, DWORD);
   // VDMDBG Function Pointers.
   INT (WINAPI *lpfVDMEnumTaskWOWEx)(DWORD, TASKENUMPROCEX, LPARAM);
   // Retrieve the OS version
   osver.dwOSVersionInfoSize = sizeof(osver);
   if (!GetVersionEx(&osver))
      return FALSE;
  
   // If Windows NT 4.0
   if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT
         && osver.dwMajorVersion == 4) {
      __try {
         // Get the procedure addresses explicitly. We do
         // this so we don't have to worry about modules
         // failing to load under OSes other than Windows NT 4.0
         // because references to PSAPI.DLL can't be resolved.
         hInstLib = LoadLibraryA("PSAPI.DLL");
         if (hInstLib == NULL)
            __leave;
         hInstLib2 = LoadLibraryA("VDMDBG.DLL");
         if (hInstLib2 == NULL)
            __leave;
         // Get procedure addresses.
         lpfEnumProcesses = (BOOL (WINAPI *)(DWORD *, DWORD, DWORD*))
               GetProcAddress(hInstLib, "EnumProcesses");
         lpfEnumProcessModules = (BOOL (WINAPI *)(HANDLE, HMODULE *,
               DWORD, LPDWORD)) GetProcAddress(hInstLib,
               "EnumProcessModules");
         lpfGetModuleBaseName = (DWORD (WINAPI *)(HANDLE, HMODULE,
               LPTSTR, DWORD)) GetProcAddress(hInstLib,
               "GetModuleBaseNameA");
         lpfVDMEnumTaskWOWEx = (INT (WINAPI *)(DWORD, TASKENUMPROCEX,
               LPARAM)) GetProcAddress(hInstLib2, "VDMEnumTaskWOWEx");
        
         if (lpfEnumProcesses == NULL
               || lpfEnumProcessModules == NULL
               || lpfGetModuleBaseName == NULL
               || lpfVDMEnumTaskWOWEx == NULL)
            __leave;
         //
         // Call the PSAPI function EnumProcesses to get all of the
         // ProcID's currently in the system.
         //
         // NOTE: In the documentation, the third parameter of
         // EnumProcesses is named cbNeeded, which implies that you
         // can call the function once to find out how much space to
         // allocate for a buffer and again to fill the buffer.
         // This is not the case. The cbNeeded parameter returns
         // the number of PIDs returned, so if your buffer size is
         // zero cbNeeded returns zero.
         //
         // NOTE: The "HeapAlloc" loop here ensures that we
         // actually allocate a buffer large enough for all the
         // PIDs in the system.
         //
         dwSize2 = 256 * sizeof(DWORD);
         do {
            if (lpdwPIDs) {
               HeapFree(GetProcessHeap(), 0, lpdwPIDs);
               dwSize2 *= 2;
            }
            lpdwPIDs = (LPDWORD) HeapAlloc(GetProcessHeap(), 0,
                  dwSize2);
            if (lpdwPIDs == NULL)
               __leave;
           
            if (!lpfEnumProcesses(lpdwPIDs, dwSize2, &dwSize))
               __leave;
         } while (dwSize == dwSize2);
         // How many ProcID's did we get?
         dwSize /= sizeof(DWORD);
         // Loop through each ProcID.
         for (dwIndex = 0; dwIndex < dwSize; dwIndex++) {
            szFileName[0] = 0;
           
            // Open the process (if we can... security does not
            // permit every process in the system to be opened).
            hProcess = OpenProcess(
                  PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                  FALSE, lpdwPIDs[dwIndex]);
            if (hProcess != NULL) {
               // Here we call EnumProcessModules to get only the
               // first module in the process. This will be the
               // EXE module for which we will retrieve the name.
               if (lpfEnumProcessModules(hProcess, &hMod,
                     sizeof(hMod), &dwSize2)) {
                  // Get the module name
                  if (!lpfGetModuleBaseName(hProcess, hMod,
                        szFileName, sizeof(szFileName)))
                     szFileName[0] = 0;
               }
               CloseHandle(hProcess);
            }
            // Regardless of OpenProcess success or failure, we
            // still call the enum func with the ProcID.
            if (!lpProc(lpdwPIDs[dwIndex], 0, szFileName, lParam))
               break;
            // Did we just bump into an NTVDM?
            if (_stricmp(szFileName, "NTVDM.EXE") == 0) {
               // Fill in some info for the 16-bit enum proc.
               sInfo.dwPID = lpdwPIDs[dwIndex];
               sInfo.lpProc = lpProc;
               sInfo.lParam = (DWORD) lParam;
               sInfo.bEnd = FALSE;
               // Enum the 16-bit stuff.
               lpfVDMEnumTaskWOWEx(lpdwPIDs[dwIndex],
                  (TASKENUMPROCEX) Enum16, (LPARAM) &sInfo);
               // Did our main enum func say quit?
               if (sInfo.bEnd)
                  break;
            }
         }
      } __finally {
         if (hInstLib)
            FreeLibrary(hInstLib);
         if (hInstLib2)
            FreeLibrary(hInstLib2);
         if (lpdwPIDs)
            HeapFree(GetProcessHeap(), 0, lpdwPIDs);
      }
   // If any OS other than Windows NT 4.0.
   } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
         || (osver.dwPlatformId == VER_PLATFORM_WIN32_NT
         && osver.dwMajorVersion > 4)) {
      __try {
         hInstLib = LoadLibraryA("Kernel32.DLL");
         if (hInstLib == NULL)
            __leave;
         // If NT-based OS, load VDMDBG.DLL.
         if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
            hInstLib2 = LoadLibraryA("VDMDBG.DLL");
            if (hInstLib2 == NULL)
               __leave;
         }
         // Get procedure addresses. We are linking to
         // these functions explicitly, because a module using
         // this code would fail to load under Windows NT,
         // which does not have the Toolhelp32
         // functions in KERNEL32.DLL.
         lpfCreateToolhelp32Snapshot =
               (HANDLE (WINAPI *)(DWORD,DWORD))
               GetProcAddress(hInstLib, "CreateToolhelp32Snapshot");
         lpfProcess32First =
               (BOOL (WINAPI *)(HANDLE,LPPROCESSENTRY32))
               GetProcAddress(hInstLib, "Process32First");
         lpfProcess32Next =
               (BOOL (WINAPI *)(HANDLE,LPPROCESSENTRY32))
               GetProcAddress(hInstLib, "Process32Next");
         if (lpfProcess32Next == NULL
               || lpfProcess32First == NULL
               || lpfCreateToolhelp32Snapshot == NULL)
            __leave;
         if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
            lpfVDMEnumTaskWOWEx = (INT (WINAPI *)(DWORD, TASKENUMPROCEX,
                  LPARAM)) GetProcAddress(hInstLib2, "VDMEnumTaskWOWEx");
            if (lpfVDMEnumTaskWOWEx == NULL)
               __leave;
         }
         // Get a handle to a Toolhelp snapshot of all processes.
         hSnapShot = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
         if (hSnapShot == INVALID_HANDLE_VALUE) {
            FreeLibrary(hInstLib);
            return FALSE;
         }
         // Get the first process' information.
         procentry.dwSize = sizeof(PROCESSENTRY32);
         bFlag = lpfProcess32First(hSnapShot, &procentry);
         // While there are processes, keep looping.
         while (bFlag) {
           
            // Call the enum func with the filename and ProcID.
            if (lpProc(procentry.th32ProcessID, 0,
                  procentry.szExeFile, lParam)) {
               // Did we just bump into an NTVDM?
               if (_stricmp(procentry.szExeFile, "NTVDM.EXE") == 0) {
                  // Fill in some info for the 16-bit enum proc.
                  sInfo.dwPID = procentry.th32ProcessID;
                  sInfo.lpProc = lpProc;
                  sInfo.lParam = (DWORD) lParam;
                  sInfo.bEnd = FALSE;
                  // Enum the 16-bit stuff.
                  lpfVDMEnumTaskWOWEx(procentry.th32ProcessID,
                     (TASKENUMPROCEX) Enum16, (LPARAM) &sInfo);
                  // Did our main enum func say quit?
                  if (sInfo.bEnd)
                     break;
               }
               procentry.dwSize = sizeof(PROCESSENTRY32);
               bFlag = lpfProcess32Next(hSnapShot, &procentry);
            } else
               bFlag = FALSE;
         }
      } __finally {
         if (hInstLib)
            FreeLibrary(hInstLib);
         if (hInstLib2)
            FreeLibrary(hInstLib2);
      }
   } else
      return FALSE;
   // Free the library.
   FreeLibrary(hInstLib);
   return TRUE;
}

BOOL WINAPI Enum16(DWORD dwThreadId, WORD hMod16, WORD hTask16,
      PSZ pszModName, PSZ pszFileName, LPARAM lpUserDefined) {
   BOOL bRet;
   EnumInfoStruct *psInfo = (EnumInfoStruct *)lpUserDefined;
   bRet = psInfo->lpProc(psInfo->dwPID, hTask16, pszFileName,
      psInfo->lParam);
   if (!bRet)
      psInfo->bEnd = TRUE;
   return !bRet;
}

BOOL CALLBACK MyProcessEnumerator(DWORD dwPID, WORD wTask,
      LPCSTR szProcess, LPARAM lParam) {
   if (wTask == 0)
      printf("%5u   %s\n", dwPID, szProcess);
   else
      printf("  %5u %s\n", wTask, szProcess);
   return TRUE;
}