MFC 에서 스크롤바에 대한 개념이 없이 스크롤바를 제어하려다가 며칠 삽질을 했습니다.

폼뷰를 생성하여 뷰로 폼형태를 보여줄때 리소스창에서 폼뷰의 다이얼로그를 매우 크게하면 자동으로 스크롤바가 생성됩니다.

그런데 리소스창에 폼뷰의 다이얼로그를 작게 그릴 경우 스크롤바가 사라집니다.

동적으로 화면의 스크롤을 지정하려면???



원하는 시점에 이 코드를 불러주면 화면의 스크롤 영역이 지정됩니다.

스크롤을 이리저리 끌다보면 폼이 같이 움직이죠..

아 삽질한 시간이 얼마인가. ㅜㅜ

CDialog 로 UI 를 구성할 때 조건에 따라서 UI 가 동적으로 생성되어야 하는 경우가 있습니다.

이때 해당 UI 의 이벤트 처리를 담당하는 함수를 어떻게 등록하는지 알아보겠습니다.

보통 CDialog 에 콤포넌트를 등록하려면 리소스 편집기에서 콤포넌트를 추가한 다음에 이벤트 핸들러를 등록합니다.

이런것들은 통합개발툴(IDE) 에서 해주는데요.. Visual Studio 가 그런 것을 자동으로 만들어주고 메시지맵을 등록시켜줍니다.
하지만 이런 경우는 콤포넌트의 위치나 생성이 정해져 있는 경우 이므로 동적으로 처리해야하는 방법은 직접 코딩을 해주어야합니다.

먼저 동적으로 처리하는 가장 확실한 방법은 직접 해당 콤포넌트를 서브클래싱 하는 방법입니다.

예를들어서  CButton 을 동적생성하여 해당 버튼이 클릭되었을때 이벤트를 처리하려면

class CMyButton : public CButton {}

이런식으로 서브클래싱한 후에 ButtonClicked 이벤트를 직접 처리해주는 것이죠.

하지만 단순한 동작을 하기 위해서 서브클래싱을 해준다면 파일이 매우 많아질 뿐더러 소스도 지저분해지게 됩니다. (사실 이게 지저분한 소스인지는 제 주관입니다.)

그래서 다른 방법을 찾아보았습니다.

지금 사용할 방법은 동적으로 등록한 콤포넌트의 이벤트 핸들을 해당 부모 윈도우인 Dialog 에서 간단하게 처리하는 방법입닏.

ON_CONTROL_RANGE 메세지 맵을 이용합니다.

예제입니다.

CMyDialog.h


CMyDialog.cpp



이벤트 처리 핸들러를 다른것으로 등록할 경우에는 다른 콤포넌트의 이벤트를 간단하게 받을 수 있습니다 .
Sqlite3 소스코드에 있는 내용입니다.


윈도우 모바일 프로그래밍을 시작하는 대부분의 사람은 어디에서부터 어떻게 시작해야 하는지 막막할 것입니다.

요즘 모바일 프로그램을 해야할 사정이 생겨서 시작하게 되었는데 혼자알기에는 아깝고, 까먹을지 몰라서 간단하게 요약하고자 합니다.

Windows Mobile 프로그래밍의 시작은 어떻게 하는것이 좋을까요??

인터넷을 뒤져보면 아주 좋은 자료들이 많습니다.

어떤 기능을 하는 코드, 어떤 에러를 잡는 방법, 어떤 프로그램에 필요한 기술 등등 각종 단편적인 수많은 자료들이 존재하기 때문에 인터넷 자료를 기반으로 시작하시는 분들이 많습니다.

이런 방법도 매우 좋은 방법이긴 합니다. 하지만 프로그램을 배우는 흐름이 뒤죽박죽으로 섞이고 인터넷의 정보가 정확한 정보가 아닐 수도 있기 때문에 예상하지 못한 많은 시행착오를 겪을 수 있습니다.

그래서 저는 다음 방법을 추천합니다.

지금 곧장 가까운 서점에 가서 마음에 드는 책을 한권 사서 처음부터 차근 차근읽으십시오.

책의 서문과 Windows Mobile 시스템에 대한 이해, 그리고 계보 등을 이해하고 체계적으로 시작하는것을 추천합니다.

다만 이 글은 Windows Mobile 프로그래밍을 예전에 해봤다가 깜빡 기억이 안나는 분들을 위해서 준비했습니다.

다음 구성으로 연재를 할 예정입니다.

Windows Mobile 빌드환경 구성하기.

Windows Mobile 첫번째 프로그램 시작하기

Windows Mobile 더버깅 하기.

Windows Mobile 인터넷 연결하기.

Windows Mobile 리소스 파일 적용하기

Windows Mobile Sqlite를 활용한 DataBase 시스템

팀에서 따로 하는 프로젝트에 doxygen 을 활용합니다.

doxygen 에 대한 설명은 여러 사이트에서 잘 설명을 해놓았습니다. 되도록이면 여기가 아닌 잘 정리된 사이트를 참고하시기 바랍니다.

이 글은 단순히 제가 참고하기 위해서 작성한 글입니다.

Doxygen 예제

// <---- 프로젝트 전체 설명
/// @mainpage 프로세스가 종료되는 시점 후킹
/// @section intro 소개
/// - 소개    : 목표로 하는 프로세스에 해당 dll 을 injection 시킨다.
/// @section Program 프로그램명
/// - 프로그램명 : ExitProcessHook
/// - 프로그램내용 : 프로세스가 종료되는 시점을 dll 에서 알아내기 위해 후킹한다.
/// @section CREATEINFO 작성정보
/// - 작성자  : Ggil
/// - 작성일  : 2009-05-19
/// @section MODIFYINFO 수정정보
/// - 수정일/수정자 : 수정내역
/// - 2009-05-20/Ggil : ExitProcess 대신 ExitProcess 를 후킹함.

// 특정 파일에 대한 설명.
/// @file TerminateProcess.cpp
/// @brief DLL 메인 소스파일. TerminateProcess 후킹하려고 이름을 정했다가 후킹함수만 변경하고 이름은 그대로 둠.

#include "stdafx.h"

 

/// @brief Dll의 진입 함수.
///
/// @param hModule 현재 dll 의 모듈 베이스
/// @param ul_reason_for_call 진입 함수의 호출 타입? 이유? 호출시점?
/// @param lpReserved 말 그대로 예약된 파라미터
/// @return 처리 결과(TRUE : 성공, FALSE : 실패)

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
 static PFN_TERM NewExitProcess_Target = NULL; // ExitProcess 함수의 포인터
 HMODULE hTargetModule = NULL;

 switch (ul_reason_for_call)
 {
 case DLL_PROCESS_ATTACH:

  break;
 case DLL_PROCESS_DETACH:

  break;
 }

    return TRUE;
}


SVN 은 여러명의 공통의 프로젝트를 관리하는데 유용한 시스템입니다.

그러므로 SVN 에 저장될 데이터는 공통의 자료만 저장되어야만 다른 사람이 불편하지 않습니다.

 

다음은 Visual Studio 2005 에서 생성된 파일들 중에 임시/개인데이터 파일의 목록입니다.

SVN에서 Add 명령으로 모두 한꺼번에 추가하지말고 선택적으로 추가하시기를 바랍니다.

 

만일 아래 파일을 SVN 에 등록할 경우 매번 충돌이 생기거나 내용수정에 따른 modified 상태로 빨간색 표시가 나타날 것입니다.

 

[ SVN 에 추가하지 말아야할 파일 확장자 ]

  • Debug, Release 폴더를 포함하여 빌드 구성요소에 추가된 폴더 및 파일들. 
  • *.ncb
  • *.vcproj.컴터이름.사용자이름
  • *.suo
  • *.aps
  • *.opt
  • *.plg

블로그에 정말 가끔씩 소스코드를 올릴때가 있습니다.

그때마다 빌드툴에서 긁어붙이기를 하면 지저분해서 속이 상하는데요..

바로 이렇게 됩니다. 그냥 긁어붙일경우...  아주 너저분합니다.

 void CXButtonXPTestDlg::OnButton2()
{
 TRACE(_T("in CXButtonXPTestDlg::OnButton2\n"));

 UpdateData(TRUE);

 CString str = _T("");
 m_edtCount2.GetWindowText(str);
 int nCount = _ttoi(str);
 if (nCount < 0)
  nCount = 0;
 nCount++;
 str.Format(_T("%d"), nCount);
 m_edtCount2.SetWindowText(str);

 BOOL bToggled = m_XButtonXP.GetToggleState();
 TRACE(_T("toggle state=%d\n"), bToggled);

 if (m_bMessageBox)
  AfxMessageBox(_T("Button 2 pressed."), MB_OK|MB_ICONINFORMATION);
}


이런 너저분함을 없애기 위해서 몇군데 찾아봤습니다.

첫번째로 http://codepad.org/  입니다. 사이트상에는 글자에 색깔도 이쁘게 입혀지는데 긁어붙이니 그렇지 않네요.

 
void CXButtonXPTestDlg::OnButton2() 
{
	TRACE(_T("in CXButtonXPTestDlg::OnButton2\n"));

	UpdateData(TRUE);

	CString str = _T("");
	m_edtCount2.GetWindowText(str);
	int nCount = _ttoi(str);
	if (nCount < 0)
		nCount = 0;
	nCount++;
	str.Format(_T("%d"), nCount);
	m_edtCount2.SetWindowText(str);

	BOOL bToggled = m_XButtonXP.GetToggleState();
	TRACE(_T("toggle state=%d\n"), bToggled);

	if (m_bMessageBox)
		AfxMessageBox(_T("Button 2 pressed."), MB_OK|MB_ICONINFORMATION);
}



그리고 두번째로

http://code.google.com/p/syntaxhighlighter/

그런데 쓰기가 좀 불편합니다. 직접 태그를 입력하면 자바스크립트가 알아서 변경시켜주는거죠.

샘플 화면입니다. <== 샘플 화면을 지우고 직접 티스토리 스타일시트를 지정해보았습니다.
http://gyuha.tistory.com/193  <== 세팅법 참고.
 

(티스토리의 스킨을 수정할 경우 소스를 올릴때마다 자동으로 적용되므로 어쩌면 편할 수도 있습니다.



세번째 입니다. 첫번째 처럼 긁어붙이기가 되므로 쓰기 편하네요. 색깔도 예쁘게 잘 나옵니다.
http://quickhighlighter.com/
 
  1. void CXButtonXPTestDlg::OnButton2()
  2. {
  3.     TRACE(_T("in CXButtonXPTestDlg::OnButton2\n"));
  4.  
  5.     UpdateData(TRUE);
  6.  
  7.     CString str = _T("");
  8.     m_edtCount2.GetWindowText(str);
  9.     int nCount = _ttoi(str);
  10.     if (nCount < 0)
  11.         nCount = 0;
  12.     nCount++;
  13.     str.Format(_T("%d"), nCount);
  14.     m_edtCount2.SetWindowText(str);
  15.  
  16.     BOOL bToggled = m_XButtonXP.GetToggleState();
  17.     TRACE(_T("toggle state=%d\n"), bToggled);
  18.  
  19.     if (m_bMessageBox)
  20.         AfxMessageBox(_T("Button 2 pressed."), MB_OK|MB_ICONINFORMATION);
  21. }


마지막으로 http://www.chamisplace.com/colorizer/cc.asp 

이 사이트는 괄호가 인상적이네요. 큼지막 합니다.

 1: void CXButtonXPTestDlg::OnButton2()
2: //=============================================================================
3:
{
4: TRACE(_T("in CXButtonXPTestDlg::OnButton2\n"));
5:
6: UpdateData(TRUE);
7:
8: CString str = _T("");
9: m_edtCount2.GetWindowText(str);
10: int nCount = _ttoi(str);
11: if (nCount < 0)
12: nCount = 0;
13: nCount++;
14: str.Format(_T("%d"), nCount);
15: m_edtCount2.SetWindowText(str);
16:
17: BOOL bToggled = m_XButtonXP.GetToggleState();
18: TRACE(_T("toggle state=%d\n"), bToggled);
19:
20: if (m_bMessageBox)
21: AfxMessageBox(_T("Button 2 pressed."), MB_OK|MB_ICONINFORMATION);
22: }



각각 장단점이 있습니다. 취향에 맞게 선택하시면 되겠네요.

다른 스레드에서 생성한 다이얼로그를 강제로 죽이려면??

pDlg->DestroyWindow() <== ?

이러면 제대로 종료되지 않습니다.

pDlg->CloseWindow() <== ?

마찬가지로 종료되지 않습니다.

SendMessage(pDlg->GetSafeHwnd(), WM_CLOSE, NULL, NULL)

종료되지 않습니다.


모달 다이얼로그를 종료시키는 방법은 EndDialog() 함수를 호출하는 방법뿐입니다.

pDlg->EndDialog(IDOK); 혹은  pDlg->EndDialog(IDCALCEL);

을 호출하면 해당 다이얼로그는 종료가됩니다.

삽질하지말자!!!

처음 시나리오.
1. LBUTTONDOWN 메세지를 받아서 최초 클릭위치 저장
2. MOUSEMOVE 메세지를 받아서 드래그 상태이면 이동한 만큼 다이얼로그 이동. 클릭위치 업데이트

이렇게 했었는데.. 뭐 가능할지도..안해봐서 모르겠지만 더 편한 방법이 있습니다.

바로 LBUTTONDOWN 메세지를 받으면 다이얼로그박스타이틀바 에 메세지를 보내는거죠.

즉 타이틀바를 클릭해서 드래그하는것 과 같은 효과를 주는겁니다.

void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
 RECT rect;
 GetWindowRect(&rect);
 if( ( point.x < rect.right  || point.x > rect.left ) ||
  ( point.y < rect.top || point.y > rect.bottom ) )
 {
  DefWindowProc(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
 }

 CDialog::OnLButtonDown(nFlags, point);
}

이러면 끝!!!

dll 이 자신이 로딩중인 프로세스의 죽는 시점을 알아내기 위해서 다음 함수를 후킹하면 됩니다.

// Ends the calling process and all its threads.
VOID WINAPI ExitProcess(
  __in  UINT uExitCode
);


어설프게 TerminateProcess 를 후킹해서 왜 안불려질까 멍청하게 고민을 하다니. ㅡㅡ;

다른프로세스에서는? 안해봤지만 후킹하지않고 ToolHelp API 으로 열심히 프로세스를 뒤지다가 없어지면 종료된 시점으로 간주하면 되지 않을까???
그냥 binary editor 으로 뒤져도 되지만 windbg 로 볼 경우 좀더 편하다.

준비물 : 분석할 exe 파일과 그 파일의 pdb

1. F6(File->Attach to a Process..) 으로 분석할 프로세스(exe) 선택.

2. 커맨드 창이 뜨면 .symfix+ c:\symbols 실행

3. File -> Symbol File Path 실행한 후 Browse.. 버튼을 클릭하여 pdb 파일이 있는 폴더를 선택.

4. 프로세스를 계속 실행시킬 경우 F5 키 누르고 멈출려면 Ctrl+Break 키 누름

5. .reload *  과 ld * 으로 심볼 다시 로딩
"ERROR : Symbol file could not be found."  에러는 다른 모듈(exe 가 로딩하는 각종 dll 등)의 심볼을 못찾으므로 발생하는 에러임. .무시

6. 마지막으로 lml 으로 제대로 로딩되었는지 확인... 실행파일의 심볼이 로딩되어 있어야함. 일반적으로 0x400000 위치.

여기까지 pdb를 로딩하는 방법.

이제 이걸 통해서 실제 심볼을 표시해보자.

x 실행파일이름!*검색할심볼명*
ex : x sample!*g_*     <== sample.exe 에서 g_ 가 들어가 있는 모든 심볼 표시
dt 실행파일이름!*검색할심볼명*
ex : dt sample!*g_*     <== sample.exe 에서 g_ 가 들어가 있는 모든 타입 심볼 표시

이러면 심볼이 주루룩 나타난다.

만일 pdb 파일이 실행파일과 싱크(?) 가 맞지 않을 경우에는 강제로 pdb 파일을 로딩해야한다.

.reload /i 실행파일.exe

그리고 다시 lml 으로 제대로 심볼을 로딩했는지 확인하면 끝!!!

마지막으로 팁으로...

심볼 이름으로 브레이크포인트 걸기 : bp 실행파일!심볼이름
특정 심볼(변수)의 정보 보기 : dt 실행파일!심볼이름
특정 심볼에 접근(쓰기)하는 경우 브포 걸기 : ? 실행파일!심볼이름   으로 주소를 찾고   ba w4 주소  를 입력함.
실행되고있는 스레드 정보 보기 : Alt + 9
해당 스레드의 콜스택 : 스래드 선택하고 kb
특정 명령어의 정보보기 : .hh 명령어

이상 끝!


CreateDirectory() 는 마지막 폴더만 생성하는 함수입니다.

다음은 원하는 Full Path 의 폴더를 생성시켜주는 함수입니다.

BOOL AutoCreateDirectory(TCHAR* dir)
{
 TCHAR path[MAX_PATH] = {0, };
 TCHAR *p = dir;
 int nStep = 0;
 BOOL bRet = FALSE;

 //   0    1    2    3
 // c:\test\1234\5678\23412
 while( true )
 {
  if (*p == '\\' || *p == NULL)
  {
   if (nStep >= 1)
   {
    _tcsncpy(path, dir, (p-dir));
    path[(p-dir)] = '\0';

    bRet = CreateDirectory(path, NULL);

    if (bRet == NULL && GetLastError() != ERROR_ALREADY_EXISTS)
    {
     TRACE("심각한 오류 : 폴더 생성 실패. 원인 %ld \n", GetLastError());
     return FALSE;
    }
   }

   if (*p == NULL)
    break;

   nStep++;
  }

  p++;
 }

 return TRUE;
}

휴~ 이넘의 지저분한 소스... 매번 느끼는거지만 초간단 플밍만 하니 소스가 이모양이지....

스피드핵은 기본적으로 타이머와 관련된 함수를 후킹해서 사용합니다.
GetTickCount(), timeGetTime(), QueryPerformanceCounter()

만일 윈도우에서 제공해주는 타이머 함수를 직접 구현한다면???

자료를 뒤져보니 Assemply 로 CPU 시간을 알아내는 코드가 있더군요.
출처 : http://abipictures.tistory.com/353

unsigned __int64 ddwCount;

_asm
{
RDTSC
mov DWORD PTR ddwCount, eax
mov DWORD PTR ddwCount+ 4, edx
}

RDTSC(Ream Time Stamp Counter) 은 8x86 CPU에서 CPU의 클럭값을 eax와 edx에 return하는 어셈입니다.


그런데 실제 돌려보니 CPU 클럭값이 초당 몇번 동작하는지 모르니 적용할려면 좀 노력을 해야할것같네요.

 int _tmain(int argc, _TCHAR* argv[])
{
 struct {
  DWORD dwTime1;
  DWORD dwTime2;
 } asmTimer, tmpTimer;

 for(int i=0; i<20; i++)
 {
  __asm
  {
   RDTSC
   mov DWORD PTR asmTimer, eax
   mov DWORD PTR asmTimer+4, edx
  }

  if (i>0)
  {
   printf("[%u]\t%lu\t[%lu]\t%lu\t[%lu]\n",
    i,
    asmTimer.dwTime1,
    asmTimer.dwTime1 - tmpTimer.dwTime1,
    asmTimer.dwTime2,
    asmTimer.dwTime2 - tmpTimer.dwTime2);
  }

  memcpy(&tmpTimer, &asmTimer, sizeof(asmTimer));

  Sleep(500);
 }
 
 return 0;
}

 [1]     4231356696      [139997214]     169     [0]
[2]     41459963        [105070563]     170     [1]
[3]     90353894        [48893931]      170     [0]
[4]     237211070       [146857176]     170     [0]
[5]     288734747       [51523677]      170     [0]
[6]     361892201       [73157454]      170     [0]
[7]     543081920       [181189719]     170     [0]
[8]     613704488       [70622568]      170     [0]
[9]     675258215       [61553727]      170     [0]
[10]    869067653       [193809438]     170     [0]
[11]    923720396       [54652743]      170     [0]
[12]    987591011       [63870615]      170     [0]
[13]    1064402699      [76811688]      170     [0]
[14]    1121647946      [57245247]      170     [0]
[15]    1170933692      [49285746]      170     [0]
[16]    1233143213      [62209521]      170     [0]
[17]    1304132819      [70989606]      170     [0]
[18]    1383210554      [79077735]      170     [0]
[19]    1434673859      [51463305]      170     [0]




 

오랜만에 드라이버를 만들려고 DDK 를 설치하고 빌드를 했다.

SOURCE 파일을 잘못 만들어서 몇시간(?)을 삽질을 했고 빌드한 드라이버를 로딩하기 위해서

간단한 로더도 만들어보고..

그러다가 빌드가 너~~무 귀찮아서 자료를 찾던중에 somma 님께서 올려두신 드라이버 편하게 빌드하는 법을 찾았다.

방법은 아래 링크를 보고 그대로 따라하세요.

http://www.hollistech.com/Resources/ddkbuild/ddkbuild.htm

출처 : http://blog.naver.com/blackpet?Redirect=Log&logNo=100004104020

요기서 확인하면 자세한 설명이 있음.

저 사이트 없어질까봐 간략정리함.

VC 6.0 에서는 잘 컴팔 되던것이..

1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(207) : error C2146: syntax error : missing ';' before identifier 'dbch_size'
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(207) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(207) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(208) : error C2146: syntax error : missing ';' before identifier 'dbch_devicetype'
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(208) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(208) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(209) : error C2146: syntax error : missing ';' before identifier 'dbch_reserved'
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(209) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(209) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(213) : error C2143: syntax error : missing ';' before '*'

간단한 해결방법은

/wd 4430

컴파일 옵션을 추가하면 해결.

그런데 헤더파일 잴 위에

#include <windows.h>

를 추가해도 해결되는군.. 왜 그런지는 모름.

친구와 함께 사용하는 Repository 를 옮길일이 발생했다.

원래는 내 피시에서 세팅해서 사용했지만 요즘 이사문제로 잠시 다른집에 얹혀 사는 입장에서

서버까지 돌려놓을수 없어서 친구에게 옮기기로 결정했고 단순히 Repository 폴더를 통째로 압축해서 보내줬다.

예전에 CVS 를 그렇게 옮겨 보았고 SVN 도 별다르게 틀리지 않을거라는 예상에.....

하지만 친구로부터 온 문자 때문에 이번에는 SVN 의 Repository 백업과 복구에 대해서 알아보았다.

SVN 의 Repository 의 백업은 여러가지가 있는것 같다.

그냥 무식하게 폴더를 통째로 백업(hardcopy) 해 놓는 방법도 그중에 하나이긴하지만 백업하는 타이밍에 데이터가 수정될 경우 문제가 발생하므로 서버를 내려놓고 백업을 하던가 다음 명령어로 백업을 할 수 있다.

svnadmin hotcopy path/to/repository path/to/backup --clean-logs

뭐..이건 SVN help 를 통해서 찾은내용이고 웹에 떠도는 내용을 토대로 실제 백업과 복구를 해보았다.

svnadmin help 명령어를 사용하면 hotcopy 이외에 여러가지 명령어가 나오는데 그중에

dump 와 load 명령어를 사용하면 된다.

* dump
- 특정 프로젝트를 백업하는 명령어
- $ svnadmin help dump
┌────────────────────────────────────────
│ dump: 사용법: svnadmin dump REPOS_PATH [-r LOWER[:UPPER]] [--incremental]
│ 파일 시스템의 내용을 stdout 으로 포터블한 형식의 'dumpfile'로 적재하며,
│ stderr로 피드백을 보냅니다. 리비젼 LOWER rev 부터 UPPER rev 까지
│ 적재합니다. 주어진 리비젼이 없다면, 모든 리비젼 트리를 적재합니다.
│ --incremental 옵션을 사용한다면, 모든 내용이 아닌 이전 버젼과의 차이만 적재됩니다.
│ 옵션:
│  -r [--revision] arg      : 리비젼 넘버 ARG ( 또는 X:Y 범위 )를 지정합니다
│  --incremental            : incremental 적재를 합니다.
│  --deltas                 : 적재된 결과물에 deltas를 사용합니다
│  -q [--quiet]             : stderr 에 대한 진행사항이 (오류에 한해서) 없습니다

└────────────────────────────────────────

* load
- 특정 프로젝트를 복구 하는 명령어
- $ svnadmin help load
┌────────────────────────────────────────
│ load: 사용법: svnadmin load REPOS_PATH
│ stdin 으로 'dumpfile' 형식의 스트림을 읽어들여, 새로운 리비젼을
│ 저장소의 파일시스템으로 커밋합니다. 이전에 저장소가
│ 비어있었다면, 기본적으로 그것의 UUID 가 스트림에 지정된
│ 한가지로 변경될것입니다. 진행 피드백은 stdout 으로 전송됩니다.
│ 옵션:
│   -q [--quiet]             : stderr 에 대한 진행사항이 (오류에 한해서) 없습니다
│   --ignore-uuid            : 스트림에 어떤 repos UUID가 발견되어도 무시합니다
│   --force-uuid             : 만약 있다면, repos UUID 를 스트림에서 발견된 것에 설정합니다,
│   --use-pre-commit-hook    : 리비전을 새로이 커밋하기 전 post-commit 훅을 호출합니다.
│   --use-post-commit-hook   : 리비전을 새로이 커밋한 뒤 post-commit 훅을 호출합니다.
│   --parent-dir arg         : 저장소의 지정된 디렉토리에 로드합니다

└────────────────────────────────────────

1. 사용자 추가 [root][ use mysql ]
> GRANT ALL ON <DATABASE 명 혹은 테이블명> TO <사용자명>@<호스트명> IDENTIFIED BY '비밀번호';
2. 사용자 로긴이 안될수 있다. 비밀번호의 해슁때문인데 이땐 암호를 한번더 변경시켜준다.
> update user set password=password('<password>') where user='<user>';
3. 데이터베이스 권한 설정
> insert into db values ('localhost', '<DATABASE 명>', '<사용자명>', 'y', 'y' ...);
4. 시스템에 적용
> flush privileges;

[서버 끄기]
\bin> mysqladmin -u root shutdown

[서버 켜기]
\bin> mysqld

참고 url : http://xxx.xxx.xxx.xxx:8080/tomcat-docs/ssl-howto.html

0. Tomcat 을 끈다.

1. JSK 1.3 이전 버전일 경우 별도의 라이브러리를 설치해야함
 JSSE 1.0.3 : http://java.sun.com/products/jsse/

2. 인증서(keystore)를 생성한다.
%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA \
  -keystore \path\to\my\keystore

3. server.xml 의 8443 을 몽땅 443 으로 고친다. (이때 https 로 접속하면 자동으로 443 번 포트를 쓰므로 포트 번호를 붙일 필요가 없다.)

4. ssl 서비스의 keystore 의 위치를 지정한다.
    <Connector port="443" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               keystorePass="암호" keystoreFile="c:\.keystore" /> <== 추가

5. 톰캣 기동!

오늘 피시에 SVN 을 설치했습니다.

그동안 쭉 CVS 관련 기술서적만 독학으로 공부하다가 회사에서 SVN 을 사용해보고는 사용의 편리함 때문에 바꾸게 되었습니다.

SVN 은 사용은 편하지만 서버쪽 세팅은 매우 복잡합니다. (물론 CVS도 매우 복잡하죠)

하지만 한번만 세팅을 해놓으면 그 이후로는 별로 수정할 일이 없습니다.

그러나.... 그 한번 세팅해놓은걸 계속 기억하고 있는것은 아니죠..

그래서 설치했던 순서대로 남겨두려고 합니다.

1. svn 서버를 다운로드 받습니다.

http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91

이 주소에서
"Windows installer with the basic win32 binaries"  버전을 다운로드 받습니다.
여러가지 버전이 많은데 다른 버전을 받으면 왠지 세팅할것이 매우 많을 것 같다는 생각이 들거든요. SVN 서버를 전문적으로 관리 하실분들은 다른 버전을 다운 받으셔도 무방합니다.

2. 다운 받은 파일을 "다음" 버튼이 사라지고 "마침" 버튼이 나올때까지 눌러서 설치합니다. (대부분의 MS Windows 응용프로그램은 이렇게 설치하죠. -_-)

3. 설치를 했으면 Repository 를 세팅해야합니다. Repository 는 영문을 그대로 번역하자면 저장소 라고 하는데 앞으로 사용할 프로젝트를 넣어두는 폴더 라고 생각하시면 됩니다. 만드는 방법은 간단합니다. 그냥 폴더를 하나 만드시면 끝납니다. -0-
d:\>mkdir svn_repo

4. 서버를 실행시켜야 합니다. 서버를 실행시키는 방법도 매우~!!! 간단합니다.
svnserve -d -r [저장소경로] 라고 입력만 하면 SVN 서버가 가동됩니다.
d:\>svnserve -d -r d:/svn_repo
|:\>svnserve -d -r d:/svn_repo

도스창(cmd.exe)에서 실행시켰다면 그 상태 그대로가 서버가 동작하는 상태입니다. 창을 꺼(Ctrl+C)버리면 서버는 종료됩니다.

↑↑↑↑↑↑↑↑↑↑↑↑↑ <== 서버 설치 끝!

초간단 서버 설치는 끝났습니다. 그럼 다음은 초간단 프로젝트 생성입니다.

이렇게 설치를 하고나면 아무짝에도 쓸모가 없습니다. 자신의 프로젝트를 직접 세팅해야 비로소 제대로된 SVN 서버세팅이라고 할 수 있습니다.

1. 설치해둔 Repository 경로로 이동한 후 다음 명령어로 프로젝트를 초기화 합니다.
d:\>cd svn_repo
d:\svn_repo>
d:\svn_repo>svnadmin create --fs-type fsfs svntestprj
위 명령어는 svntestprj 라는 이름으로 파일시스템 타입이 DB 를 생성하는 명령어 입니다.
만일 버클리 타입의 DB를 생성하려면 다음과 같이 생성해야합니다.
d:\svn_repo>svnadmin create --fs-type bdb svntestprj
버클리? 파일시스템 DB? 둘의 차이점은 도움말을 참고하세요.

↑↑↑↑↑↑↑↑↑↑↑↑↑ <== 프로젝트 생성 끝!

마지막으로 프로젝트 세팅까지 끝냈으면 서버 관리를 좀더 편하게 하는 툴을 사용하는것을 권장 합니다.
매번 PC를 켜서 로그인 후에 커맨드창을 열어서 서버 실행 명령어를 치는것은 여간 귀찮은 작업이 아닙니다.

이러한 귀찮은 작업을 손쉽게 처리해주는 툴을 PYRASIS 라는 분께서 제작하여 공개하고 있습니다.
http://www.pyrasis.com/main/SVNSERVEManager

매우 편리하므로 꼭! 설치하셔서 서비스모드로 서버를 실행시키세요. PC의 전원버튼을 누르는것 만으로 SVN 서버는 잘 동작할 것입니다.

이상 SVN 서버 초간단 설치방법을 끝내겠습니다.

SVN 의 복잡한 세팅(권한 문제, 접속방법 등등 여러가지) 는 다음을 참고하세요.

1. 그림과 함께하는 설치방법(저보다 더 설명 잘해놓았다는)

[각종 세팅방법]



사용자 삽입 이미지

게임가드 에러전송 시스템을 구상하고 있는 도중에 발견한 WoW 에러 전송화면.

어떤 소프트웨어이든 에러는 발생할 수 있습니다.

100% 완벽한 소프트웨어는 존재 하지 않으니까요.

누구나 실수는 합니다. 가장 이상적인것은 그 실수를 하지 않는 것이지만 현실적으로 불가능 합니다.

다만 그 실수를 최대한 빠르게 수습하는 차선책으로 보완을 한다면 100% 는 아니지만 99.999% 의 완벽한 소프트웨어가 될 수 있습니다.

에러를 수집할 수 있는 시스템은 그래서 필수라고 생각되네요.

소프트웨어를 사용하는 사람들이 참여하는 완벽한 제품 만들기...

보다 유저 친화적인 에러 전송화면과 정확한 보고내용을 가진 에러수집 시스템은 수많은 QA팀 인원을 확충하는 가장 효율적일 것입니다.

드라이버 첨부터 공부하는사람들...

드라이버 고수들이 누구나 추천하는 그책

"WINDOWS DRIVER MODEL"

본인도 이 책으로 드라이버에 입문(?) 을 했다.

그리고 일주일만에 포기했다. -_-;

이 책은 드라이버 입문자에게는 포기를 하게끔 만드는 강력한 마력이 있다.

왜냐하면!!!!!

처음 그걸 보면.. 이해가 안된다. 이해를 할 수 없다.

깡으로 반권을 읽었지만 결국 포기하고 말았다.

하지만 고수들이 추천했다면 당연히 좋은책임은 분명하다. 단지 입문자!!! 에게는 비추라는게 헤딩을 해본 본인의 생각이다.

그럼 나는 뭐 이 입문자를 벗어나서 드라이버를 자유자제로 제작하느냐??? 당연히 아니다.

오늘 첨으로 빌드해봤다. -_-;

그리고 앞으로 계속 연구를 해 볼것이다.

단지 입문자가 드라이버의 세계에 접근하기 편한 좋은 강좌를 모아서 링크를 올려놓고 이걸 통해서 나처럼 좌절하지 않기를 바라는 마음이다.

그 입문서를 모두 읽어 본 후에 비로소 WINDOWS DRIVER MODEL 을 읽는다면 아마도 이 책이 좋다~ 라고 생각할 것이다. (물론 본인의 생각은 아니다. 고수(?)의 의견을 빌리자면 그렇단 얘기다.)

아래 링크는 쉽게 드라이버의 세계에 입문하기 위해서 많은 도움을 주는 아주 좋은 조언자이니 꼭 읽어보길 바란다.


[초보자를 위한 Kernel based windows rootkit -1부]
http://beist.org/research/public/beginnerwinrootkit/beginnerwinrootkit.pdf
 - beist 랩에서 발견한 기초룻킷 강좌. 여기에 간단하게 드라이버 제작에 대한 설명이 포함되어 있다. 지금 읽으면서 처음 드라이버를 빌드할 수 있도록 가이드라인을 제시해주고 있다.


[드라이버 쪼물딱 거리기 1~3탄]
http://somma.egloos.com/2710282  <== 1탄
http://somma.egloos.com/2710303  <== 2탄
http://somma.egloos.com/2731001  <== 3탄
 - 유명한 쏘마님의 드라이버 입문 강좌이다.

[비주얼스튜디오에서 DDK Build를...]
http://hongyver.pe.kr/ttblog/705 
  - 커맨드라인을 벗어난 빌드환경을 구성하는데 많은 도움이 된다고 한다. 물론 해볼 예정.

[MS 사이트에서 찾은 기초자료]
http://download.microsoft.com/download/5/D/6/5D6EAF2B-7DDF-476B-93DC-7CF0072878E6/DrvDev_Intro.doc
  - 드라이버 빌드에 대한 기본적인 설명 문서

하나더 있는데 "은조님의 드라이버강좌" 홍선이 보내주기로 했으니 보내주면 링크 ㄲ (누가 김은조님이라고 했더라?)




늘 그렇지만..

mysql 문법은 개발할때만 필요하기 때문에 항상 까먹는다...

DB운영 같은걸 한다면 안까먹겠지만 개발자이다보니...

배끼는것만 잘하면 장땡

한번씩 정말 기본적인것에 에러가 나서 시간을 허비하는 경우가 종종 있다.

오늘도 간단한 SendInput 함수를 이용한 예제를 만드는데 컴파일 에러가 나서 몇십분을 삽질한 경우인데 아무래도 다음번에도 똑같은 실수를 할까봐 미리 정리해본다.

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-1279597-1";
urchinTracker();
</script>

스킨 최하단에 기입 ㄱㄱㄱ

디버깅을 하기 위한 방법에는 여러가지가 있지만

이 방법은 정공법으로써 pdb 와시스템이 남기는 디버깅 정보를 활용하는 방법이다.

참고로 나는 drwtsn32 를 띄우지 않고 ollydbg 를 레지스트리에 등록해놓고 디버깅을 하지만..

1탄.




2탄.



3탄..


뭔가 특별한 쿼리가 있는 줄 알았다. ㅡㅡ;

insert into 저장할테이블 select 컬럼1, 컬럼2, ... from 가져올테이블

이게 끝이라니..

왜 서비스가 실행되지 않는지 궁금하시다????

에러코드도 제대로 남기지 않고...

그렇다고 로그파일을 남기는것도 아니고..

그러다가 발견한 팁

mysqld-nt --defaults-file="my.ini경로" --consol

이러면 어떤 에러가 났는지 나타남.

인터넷 보고 긁어온 자료.

출처 : http://blog.naver.com/lovemusic0/70024980886

+ Recent posts