2009년 10월 29일 목요일

가끔 디버그 모드에서 디버깅 정보 저장 안할때,

 

또는 exception dump메세지가 안 나올 경우..

 

 

'디버깅 정보를 찾을 수 없거나 정보가 일치하지 않습니다. 이진 파일이 디버그 정보를 사용하여 빌드되지 않았습니다.'

이런 문장을 보거나, 혹은 디버깅은 되는데 지역 변수를 조사하지 못할 때

일단 이렇게 하니깐 제대로 되더라..

구성 속성 -> 링커 -> 디버깅 -> 디버그 정보 생성 : 예(/DEBUG)

구성 속성 -> C/C++ -> 일반 -> 디버깅 정보 형식 -> 편집하며 계속하기를 위한 프로그램 데이터베이스(/ZI)

구성 속성 -> C/C++ -> 최적화 -> 최적화 : 사용 안 함(/Od)

 

 

2009년 10월 28일 수요일

CRegKey 사용 예제

레지스트리 사용예제는 많지만 대부분 API를 이용한 예제인지라 CRegKey 클래스 사용예제를 한번 만들어봤다. 아마 자주 사용하는 예제 중에 하나가 아닐까 싶다. 소스파일도 첨부해둔다.

#include <atlbase.h>

void CCRegKeyExDlg::OnBnClickedButton1()
{
 //DWORD 저장
 CRegKey RegKey;
 
 if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS) //키가 존재하면
 {
  RegKey.SetDWORDValue(L"DWORD", 1); //DWORD라는 네임으로 "1" 값을 저장.
 
  RegKey.Close(); //오브젝트를 닫는다.
 }
}
void CCRegKeyExDlg::OnBnClickedButton2()
{
 //String 저장
 CRegKey RegKey;
 //if(RegKey.Create(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS) //(키 생성을 성공하면)키 생성과 동시에 값생성가능.
 if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS) //키가 존재하면
 {
  RegKey.SetStringValue(L"String", L"C:\\Program Files\\"); //String이라는 네임으로 지정한 문자저장 경로를 저장할때는 역슬레쉬 두개사용.
 
  RegKey.Close();
 }
}
void CCRegKeyExDlg::OnBnClickedButton3()
{
  //DWORD 읽기
 DWORD dwValue;
 DWORD dwSize = 1023;
 
 CRegKey RegKey;
  if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS) //키가 존재하면
  {
  if(RegKey.QueryDWORDValue(L"DWORD", dwValue) == ERROR_SUCCESS) //값이 존재하면 DWORD안에 데이타를 읽어온다.
  {
   RegKey.Close();//닫는다.
   CString strValue;
   strValue.Format(L"%d", dwValue);
   AfxMessageBox(strValue);
  }
  }
}
void CCRegKeyExDlg::OnBnClickedButton4()
{
  //String 읽기
 CString strValue;
 DWORD dwSize = 1023;
 
 CRegKey RegKey;
  if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS)
  {
  if(RegKey.QueryStringValue(L"String", strValue.GetBuffer(dwSize), &dwSize) == ERROR_SUCCESS)  //값(String)이 존재하면 GetBuffer를 사용하여 지정된 크기의 버퍼를 읽어온다.
  {
   RegKey.Close();//닫는다.
   strValue.ReleaseBuffer(); //읽어온 버퍼외에 필요없는 바이트를 버린다.
   AfxMessageBox(strValue); //최종적으로 리턴받은 strValue 값을 메시지박스에 출력한다.
  }
  }
}
void CCRegKeyExDlg::OnBnClickedButton5()
{
  //Value 삭제
 CRegKey RegKey;
 
 if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS)
  {
  RegKey.DeleteValue(L"DWORD");
  RegKey.DeleteValue(L"String");
  RegKey.Close();
 }
 
}
void CCRegKeyExDlg::OnBnClickedButton6()
{
 //Key 삭제
 CRegKey RegKey;
 
 if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE") == ERROR_SUCCESS)
  {
  RegKey.DeleteSubKey(L"TestProg");
  RegKey.Close();
 }
}
void CCRegKeyExDlg::OnBnClickedButton7()
{
 //Key 생성
 CRegKey RegKey;
 
 if(RegKey.Create(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS) //키 생성을 성공하면
 {
    RegKey.Close();
 }
}

2009년 10월 27일 화요일

VC 각 나라의 언어 코드


각 나라의 언어코드 입니다. 참조하세요..^^

  Language Name      Language ID
  -------------       -----------
                          
  No Language        0x0400
  Albanian            0x041c
  Arabic             0x0401
  Bahasa           0x0421
  Belgian Dutch        0x0813
  Belgian French        0x080c
  Brazilian Portuguese      0x0416
  Bulgarian          0x0402
  Catalan          0x0403
  Croato-Serbian (Latin)     0x041a
  Czech            0x0405
  Danish           0x0406
  Dutch           0x0413
  English (Aus.)         0x0c09
  English (U.K.)         0x0809
  English (U.S.)         0x0409
  Finnish          0x040b
  French           0x040c
  French (Canadian)     0x0c0c
  German           0x0407
  Greek            0x0408
  Hebrew          0x040d
  Hungarian          0x040e
  Icelandic          0x040f
  Italian            0x0410
  Japanese          0x0411
  Korean            0x0412
  Norwegian (Bokmal)     0x0414
  Norwegian (Nynorsk)    0x0814
  Polish           0x0415
  Portuguese          0x0816
  Rhaeto-Romanic         0x0417
  Romanian           0x0418
  Russian           0x0419
  Serbo-Croatian (Cyrillic)    0x081a
  Simplified Chinese      0x0804
  Slovak           0x041b
  Spanish (Castilian)     0x040a
  Spanish (Mexican)     0x080a
  Swedish          0x041d
  Swiss French         0x100c
  Swiss German        0x0807
  Swiss Italian        0x0810
  Thai            0x041e
  Traditional Chinese     0x0404
  Turkish          0x041f
  Urdu            0x0420

2009년 10월 25일 일요일

응용프로그램의 이벤트 로그 깔끔하게 저장하기

윈도즈의 서비스 프로그램에서 서비스 프로그램의 상태를 표시하는 방법으로 이벤트 로깅이 애용됩지요.

HANDLE hEventSource = RegisterEventSource(NULL, GetEventSource());

ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, GS_INFO_GENERAL, NULL, 2, 0, lpszStrings, NULL);
DeregisterEventSource(hEventSource);

그런데, 이렇게만 호출한 후 이벤트 표시기를 통해 이벤트를 보면 지저분한 메시지들이 실제 메시지 앞에 표시됩니다.

The description for Event ID ( 258 ) in Source ( gsService ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event: GS Service Report: , Java Process started: Process Handle=0x7c, Process Id=3504.

RegisterEventSource에 사용한 이벤트명이 이벤트 소스로 등록되어 있지 않아서 생기는 문제인데, 이문제를 해결하기 위한 절차가 절차를 알아봅시다.

 

1. 메시지 파일의 생성

; // ***** GSMsg.mc *****
; // This is the header section.

SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
    Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
    Warning=0x2:STATUS_SEVERITY_WARNING
    Error=0x3:STATUS_SEVERITY_ERROR
    )

FacilityNames=(System=0x0:FACILITY_SYSTEM
    Runtime=0x2:FACILITY_RUNTIME
    Stubs=0x3:FACILITY_STUBS
    Io=0x4:FACILITY_IO_ERROR_CODE
)

LanguageNames=(English=0x409:MSG00409)
;LanguageNames=(Korean=0x412:MSG00412)

; // The following are message definitions.
MessageIdTypedef=DWORD

MessageId=0x101
Severity=Error
Facility=Runtime
SymbolicName=GS_ERROR_GENERAL
Language=English
General Error: %1 %2

.

 

MessageId=0x102
Severity=Informational
Facility=Runtime
SymbolicName=GS_INFO_GENERAL
Language=English
Information: %1 %2
.

2. 메시지 파일을 메시지 컴파일러(mc)로 컴파일

mc -h $(InputDir) -r $(InputDir) $(InputPath)

-h dir: 헤더파일 출력폴더 지정
-r dir: 리소스파일 출력폴더 지정

-u: 메시지 파일이 유니코드 파일

-U: 출력 .bin파일을 유니코드 파일로 지정

이렇게 하면 GSMsg.h, GSMsg.rc, 그리고 MSG00409.bin (MSG00412.bin) 파일이 생성됩니다. 생성된 파일은 일반 헤더와 리소스처럼 VC 프로젝트에 추가해 컴파일 해줍니다. 그러면 생성된 EXE나 DLL에 메시지 정보가 포함됩니다.

 

3. 메시지 소스를 레지스트리에 등록

   메시지를 실행파일에 포함했으면, 이제 그 정보를 이벤트표시기에 그 정보를 알려줘야 하는데, 윈도즈의 레지스트리가 이용됩니다.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\EventSourceName

EventMessageFile(REG_EXPAND_SZ): C:\Program Files\gsservice\GSService.exe

TypesSupported(REG_DWORD): 7 (EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE)

좀 번거롭나요? 그래도 완성도를 높이려면 좀 수고를 해야겠죠. 그러면 이벤트 메시지가 깔끔해집니다.

Information: GS Service Report:  Java Process started: Process Handle=0x7c, Process Id=3504

자바 프로그램을 윈도즈 서비스로 만들기에 첨부된 소스의 프로젝트 파일에는 메시지컴파일과 리소스컴파일과정이 포함되어 있습니다.

2009년 10월 15일 목요일

HttpAddRequestHeaders에 cookie값을 구울때 주의사항

HttpAddRequestHeaders에 cookie값을 넣을때 일반적으로 안되는 상황이 벌어진다..

 

그럴때

 

HttpOpenRequest에서 INTERNET_FALG_NO_COOKIES 옵션을 넣으면 바로 구울 수 있다.

 

 

 

2009년 10월 14일 수요일

DWebBrowserEvent2 처리하기


#include <exdispid.h>

#define _TBROWSER_NID_ 1

// Define the sWeb events to be handled:

static _ATL_FUNC_INFO StatusTextChangeInfo = {CC_STDCALL, VT_EMPTY, 1, {VT_BSTR}};
static _ATL_FUNC_INFO WindowResizeInfo = { CC_STDCALL, VT_EMPTY, 2, {VT_I4, VT_I4} };
static _ATL_FUNC_INFO DownloadBeginInfo = {CC_STDCALL, VT_EMPTY, 0, {NULL}};
static _ATL_FUNC_INFO WindowClosingInfo = { CC_STDCALL, VT_EMPTY, 2, { VT_BOOL, VT_BOOL } };
static _ATL_FUNC_INFO NewWindow2Info = {CC_STDCALL, VT_EMPTY, 2, {VT_BYREF|VT_BOOL,VT_BYREF|VT_DISPATCH}};
static _ATL_FUNC_INFO CommandStateChangeInfo = {CC_STDCALL, VT_EMPTY, 2, {VT_I4,VT_BOOL}};
static _ATL_FUNC_INFO BeforeNavigate2Info = {CC_STDCALL, VT_EMPTY, 7, {VT_DISPATCH,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_BOOL}};
static _ATL_FUNC_INFO ProgressChangeInfo = {CC_STDCALL, VT_EMPTY, 2, {VT_I4,VT_I4}};
static _ATL_FUNC_INFO NavigateComlete2Info = {CC_STDCALL, VT_EMPTY, 2, {VT_DISPATCH, VT_BYREF|VT_VARIANT}};
static _ATL_FUNC_INFO OnVisibleInfo = {CC_STDCALL, VT_EMPTY, 1, {VT_BOOL}};

 

template <class T/*, _ATL_FUNC_INFO* info*/>
class TBrowserEvents : public IDispEventSimpleImpl<_TBROWSER_NID_, TBrowserEvents<T>, &DIID_DWebBrowserEvents2>
{
protected:
 IWebBrowser2* mWebBrowser;
 BOOL     mInitial;
 //DECLARE_DYNCREATE( TBrowserEvents<T> )

 //DECLARE_EVENTSINK_MAP()

 void OnWindowClosing( BOOL bIsChildWindow, BOOL* pbCancel );

public:


 BEGIN_SINK_MAP(TBrowserEvents)

  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 102, __StatusTextChange, &StatusTextChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 108, __ProgressChange, &ProgressChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, DISPID_WINDOWRESIZE, __WindowResize, &ProgressChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 105, __CommandStateChange, &CommandStateChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 106, __DownloadBegin, &DownloadBeginInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 104, __DownloadComplete, &DownloadBeginInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 113, __TitleChange, &StatusTextChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 252, __NavigateComplete2, &NavigateComlete2Info)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 250, __BeforeNavigate2, &BeforeNavigate2Info)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 112, __PropertyChange, &StatusTextChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, DISPID_NEWWINDOW2,/* 251,*/ __NewWindow2, &NewWindow2Info)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 259, __DocumentComplete, &NavigateComlete2Info)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, DISPID_ONQUIT, __OnQuit, &DownloadBeginInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 254, __OnVisible, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 255, __OnToolBar, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 256, __OnMenuBar, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 257, __OnStatusBar, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 258, __OnFullScreen, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 260, __OnTheaterMode, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, DISPID_WINDOWCLOSING, __OnWindowClosing, &WindowClosingInfo)
  SINK_ENTRY_EX( _TBROWSER_NID_, DIID_DWebBrowserEvents2, DISPID_QUIT, __Quit)

  END_SINK_MAP()

 T* mOwner;

 TBrowserEvents(T* Owner, IWebBrowser2* pWebBrowser)
 {
  initialize( Owner, pWebBrowser );
 }

 TBrowserEvents()
 {
 }

 void initialize( T* Owner, IWebBrowser2* pWebBrowser )
 {
  mWebBrowser = pWebBrowser;
  DispEventAdvise( dynamic_cast<IUnknown*>(mWebBrowser) );
  mInitial = TRUE;
  mOwner = Owner;
 }

 ~TBrowserEvents(void)
 {
  DispEventUnadvise( dynamic_cast<IUnknown*>(mWebBrowser) );
 }

 void __stdcall __StatusTextChange(/*[in]*/ BSTR bstrText) {  }

 void __stdcall __ProgressChange(/*[in]*/ long progress, /*[in]*/ long progressMax) {  }

 void __stdcall __WindowResize(/*[in]*/ long progress, /*[in]*/ long progressMax) {  }

 void __stdcall __CommandStateChange(/*[in]*/ long Command, /*[in]*/ VARIANT_BOOL Enable) {  }

 void __stdcall __DownloadBegin() {  }

  void __stdcall __DownloadComplete() {  }

 void __stdcall __TitleChange(/*[in]*/ BSTR bstrText) {  }

 void __stdcall __NavigateComplete2(/*[in]*/ IDispatch* pDisp, /*[in]*/ VARIANT* URL) {  }

 void __stdcall __BeforeNavigate2(/*[in]*/ IDispatch* pDisp, /*[in]*/ VARIANT* URL, /*[in]*/ VARIANT* Flags,
  /*[in]*/ VARIANT* TargetFrameName, /*[in]*/ VARIANT* PostData, /*[in]*/ VARIANT* Headers,
  /*[out]*/ VARIANT_BOOL* Cancel) {  }

 void __stdcall __PropertyChange(/*[in]*/ BSTR bstrProperty) {  }

 void __stdcall __NewWindow2(/*[out]*/ IDispatch** ppDisp, /*[out]*/ VARIANT_BOOL* Cancel) {  }

  void __stdcall __DocumentComplete(/*[in]*/ IDispatch* pDisp, /*[in]*/ VARIANT* URL) {  }

 void __stdcall __OnQuit() {  }

 void __stdcall __Quit() {  }

 //void __stdcall __OnWindowClosing() { }

 void __stdcall __OnVisible(/*[in]*/ VARIANT_BOOL Visible) { }

 void __stdcall __OnToolBar(/*[in]*/ VARIANT_BOOL ToolBar) { }

 void __stdcall __OnMenuBar(/*[in]*/ VARIANT_BOOL MenuBar) {  }

 void __stdcall __OnStatusBar(/*[in]*/ VARIANT_BOOL StatusBar) {  }

 void __stdcall __OnFullScreen(/*[in]*/ VARIANT_BOOL FullScreen) {  }

 void __stdcall __OnTheaterMode(/*[in]*/ VARIANT_BOOL TheaterMode) {  }

 void __stdcall __OnWindowClosing( VARIANT_BOOL IsChildWindow, VARIANT_BOOL* Cancel ) {  }


};

 

 

아공 만타..

 

함수 인자가 틀리면 에러 난다..

 

적용은 이런 식으로

TBrowserEvents<CMainDlg>* mEvent;

mEvent = new TBrowserEvents<CMainDlg>(this, pWB2);

 

pWB2 는 IWebBrowser2임..

 

이벤트 처리는 이런 식으로

 

void TBrowserEvents<CMainDlg>::__DocumentComplete(/*[in]*/ IDispatch* pDisp, /*[in]*/ VARIANT* URL)
{
 //< @ summary : 로그인 처리하는 부분을 넣어야 함..
 mOwner->documentCmpl(  );
}

void TBrowserEvents<CMainDlg>::__NewWindow2(/*[out]*/ IDispatch** ppDisp, /*[out]*/ VARIANT_BOOL* Cancel)
{
  mOwner->popup( ppDisp, Cancel );
}

IWebBrowser2 ctrl 동적 생성

CComQIPtr<IWebBrowser2> pWB2;

WebRenderCtrl mRender; // 웹 콘트롤 상속체 ( class WebRenderCtrl : public CWindowImpl<WebRenderCtrl, CAxWindow>

 

...

 

CComPtr<IUnkown> punkCtrl;

mRender.Create( m_hWnd, 0, 0, WS_CHILD|WS_VISIBLE, 0, 31011 );

mRender.CreateControlEx( _T("Shell.Explorer"), NULL, NULL, &punkCtrl );
pWB2 = punkCtrl;

 

이렇게 하면 동적으로 생성된다..