반응형

 

C++ Ping 예제소스로 입력한 아이피의 네트워크 연결을 확인할 수 있다.


 

# 개발환경

  • 개발도구 : Visual Studio Community 2017

 

# 결과

  • 입력한 아이피(127.0.0.1)로 ping 명령어 전송함.
  • 정상 ping 송수신 시 OK, 비정상인 경우 Not OK


# 예제소스

  • _popen, _pclose 함수를 사용하여 명령프롬프트(CMD) 실행함.
  • ping -n 1 -w 1 127.0.0.1 | findstr TTL
#include <iostream>

int sendPing(char* ipAddr);

int main()
{
    char ipAddr[128] = "127.0.0.1";
    int flagChk = sendPing(ipAddr);
    if(flagChk==1) printf("OK\n");
    else               printf("Not OK\n");

    return 1;
}

int sendPing(char* ipAddr){
    FILE* cmdWnd;
    char cmdPing[64];
    char buf[128] = {0, };

    bool flagPingOk = 0;
    sprintf(cmdPing, "ping -n 1 -w 1 %s | findstr TTL", ipAddr);
    cmdWnd = _popen(cmdPing, "r");
    if(cmdWnd != NULL){
        int bufLineCnt = 0;
        while(fgets(buf, 128, cmdWnd) != NULL){
            printf("Reply from %s : bytes=32, time<1ms, TTL=128\n", ipAddr);
            bufLineCnt++;
        }

        if(bufLineCnt > 0) flagPingOk = 1; // Connected
        else                   flagPingOk = 0; // Not Connected
    }
    _pclose(cmdWnd);

    return flagPingOk;
}

감사합니다.

 

잘못된 정보나 오타 및 수정사항이 있을 경우 댓글로 달아주시면 감사하겠습니다. 

 


 

반응형
반응형

 

코드를 디버깅할 때 콘솔(console)창을 자주 애용합니다.

한 때, 무의식적으로 콘솔창에 클릭하거나 드래그한 것도 모르는 채로 중간에 멈추는 현상을 경험한 적이 있습니다.

실수를 모르고 간헐적으로 장애를 발생하는구나 하면서 버그를 찾을려는 헛수고를 한 적이 있었습니다.

이를 방지하고자 콘솔창 마우스 드래그, 키보드 입력을 비활성화를 할 수 있는 코드를 알려드립니다.


 

# 개발 환경

운영체제 : Windows 10 Pro 64bit

개발도구 : Visual Studio 2013 Professional


 

# 사용한 API

#include <consoleapi.h>

HANDLE WINAPI GetStdHandle(
  DWORD nStdHandle
);


BOOL WINAPI GetConsoleMode(
  _In_  HANDLE  hConsoleHandle,
  _Out_ LPDWORD lpMode
);


BOOL WINAPI SetConsoleMode(
  _In_ HANDLE hConsoleHandle,
  _In_ DWORD  dwMode
);

 

# 문제점

(왼쪽) 마우스 클릭한 경우

(오른쪽) 마우스 드래그한 경우


 

# 전체 예제 소스

- main함수에서 Console Handle을 받아 Console 설정

#include <stdio.h>
#include <consoleapi.h>

int main(void)
{
    DWORD consoleModePrev;
    HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
    GetConsoleMode(handle, &consoleModePrev);
    SetConsoleMode(handle, consoleModePrev & ~ENABLE_QUICK_EDIT_MODE);

    int count = 0;
    while(1){
        printf("counting : %d\n", count++);
        Sleep(1000);
    }

    return 1;
}

 

# 단위 분석

int main

DWORD consoleModePrev;
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode(handle, &consoleModePrev);
SetConsoleMode(handle, consoleModePrev & ~ENABLE_QUICK_EDIT_MODE);
  • GetStdHandle : 콘솔 입력 버퍼(STD_INPUT_HANDLE) 에서 읽거나 쓸 수 있는 핸들 반환
  • GetConsoleMode : 핸들로 통해서 설정된 콘솔 모드를 consoleModePrev 에 저장
  • SetConsoleMode : 콘솔 화면 버퍼(handle)의 출력 모드를 마우스/키보드 미입력모드(~ENABLE_QUICK_EDIT_MODE)로 이전 모드(consoleModePrev)와 AND 연산으로 설정

 


감사합니다.

 

잘못된 정보나 오타 및 수정사항이 있을 경우 댓글로 달아주시면 감사하겠습니다. 

 


반응형
반응형

 

Win32 API : FindWindow( ) 을 이용하여 실행될 MFC 프로그램이 중복으로 실행되지 않도록 확인합니다.


 

# 개발 환경

운영체제 : Windows 10 Pro 64bit

개발도구 : Visual Studio 2013 Professional


 

# 사용한 API

#include <WinUser.h>

HWND FindWindowA(
  LPCSTR lpClassName,
  LPCSTR lpWindowName
);

 

# 결과

  • A, B는 같은 이름으로 된 프로그램
  • A 프로그램 실행 중 B 프로그램을 실행할 경우 B 프로그램에서 중복 메시지 출력

 

# 전체 예제 소스

  • OnInitDialog 함수에서 checkRunning( ) 호출
  • checkRunning( ) 반환된 값으로 프로그램 중복 처리
BOOL CMFCApplication1Dlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    SetIcon(m_hIcon, TRUE);	
    SetIcon(m_hIcon, FALSE);


    CString windowTitle = L"Test_program";

    bool flagRunning;
    for(int i=0; i<50; i++){
        if(checkRunning(windowTitle) == false){
            flagRunning = false;
            break;
        }else{
            flagRunning = true;
        }
    }

    if(flagRunning == true){
        AfxMessageBox(windowTitle + L" is already running.");
        exit(1);
    }

    SetWindowText(windowTitle);

    return TRUE;
}

bool CMFCApplication1Dlg::checkRunning(CString windowTitle)
{
    HWND hwnd = ::FindWindow(NULL, windowTitle);
    CWnd* cwnd  = CWnd::FindWindow(NULL, windowTitle);
    if (hwnd && ::IsWindow(*cwnd)) return true;
    else                           return false;
}

 

# 단위 분석

- checkRunning (CString windowTitle)

bool CMFCApplication1Dlg::checkRunning(CString windowTitle)
{
    HWND hwnd = ::FindWindow(NULL, windowTitle);
    CWnd* cwnd  = CWnd::FindWindow(NULL, windowTitle);
    if (hwnd && ::IsWindow(*cwnd)) return true;
    else                           return false;
}
  • FindWindow(...) 함수를 사용하여 windowTitle 프로그램 이름 변수로 현재 실행된 프로그램 이름들을 비교
  • HWND는 윈도우 핸들, CWnd는 MFC클래스
  • hwnd와 cwnd가 'true' 인 경우 같은 이름으로 프로그램이 실행되고 있음을 알 수 있음
  • 반환 값
    - true : 같은 이름으로 프로그램이 실행되고 있음(중복O)
    - false : 같은 이름으로 프로그램이 실행되고 있지 않음(중복X)

- SetWindowText

SetWindowText(windowTitle);
  • 프로그램 캡션(caption) 이름 변경 함수

감사합니다.

 

잘못된 정보나 오타 및 수정사항이 있을 경우 댓글로 달아주시면 감사하겠습니다. 

 


반응형
반응형

 

.ini 파일에서 단어를 읽어(read) 값을 변수에 저장하거나, 변수 값을 .ini 파일에 입력한 단어와 값을 저장(write)할 수 있습니다.


 

# 개발 환경

운영체제 : Windows 10 Pro 64bit

개발도구 : Visual Studio 2013 Professional


 

# 사용한 API

#include <winbase.h>

DWORD GetPrivateProfileString( // read
  [in]  LPCTSTR lpAppName,	// section이름 읽기
  [in]  LPCTSTR lpKeyName,	// section이름에서 변수이름 읽기
  [in]  LPCTSTR lpDefault,	// 변수이름이 없는 경우 초기값 설정
  [out] LPTSTR  lpReturnedString, // 값을 받는 변수
  [in]  DWORD   nSize,		// 받는 값의 길이
  [in]  LPCTSTR lpFileName	// 저장할 파일 경로
);

BOOL WritePrivateProfileString( // write
  [in] LPCSTR lpAppName,	// section이름 읽기
  [in] LPCSTR lpKeyName,	// section이름에서 변수이름 읽기
  [in] LPCSTR lpString,		// 읽은 변수이름에 값 쓰기
  [in] LPCSTR lpFileName	// 저장할 파일 경로
);

DWORD GetModuleFileName( // open
  HMODULE hModule,	// 현재 모듈(NULL를 한 경우 자기자신의 실행경로 반환함)
  LPSTR   lpFilename,	// 실행경로 받을 변수
  DWORD   nSize		// 실행경로 버퍼 길이
);

 

# 결과

(왼쪽) GetPrivateProfileString

(오른쪽) WritePrivateProfileString


 

# 전체 예제 소스

- Main 함수에서 ini2para, para2ini 호출

- ini2para 함수에서 read_iniFile 호출 (.ini 파일 읽기)

- para2ini 함수에서 write_iniFile 호출 (.ini 파일 쓰기)

#include <stdio.h>
#include <atlstr.h>
#include <WinBase.h>

void ini2para(CString);
void para2ini(CString);
int read_iniFile(CString, CString, CString);
void write_iniFile(CString, CString, CString, CString);

int main(void)
{
    TCHAR tExePath[256];
    GetModuleFileName(NULL, tExePath, sizeof(TCHAR)*256);
    CString csExePath(tExePath);

    CString iniFilePath = csExePath.Left(csExePath.ReverseFind('\\')) + L"\\test.ini";
    ini2para(iniFilePath);

    para2ini(iniFilePath);
}

void ini2para(CString iniFilePath)
{
    int count = read_iniFile(iniFilePath, L"TEST", L"count");

    printf("read count val = %d\n", count);
}


void para2ini(CString iniFilePath)
{
    write_iniFile(iniFilePath, L"TEST", L"count", L"999");
}


int read_iniFile(CString iniFilePath, CString section, CString var)
{
    TCHAR tReadVal[1024];
    GetPrivateProfileString(section, var, NULL, tReadVal, 32, iniFilePath);
	
    return _ttoi(tReadVal);
}


void write_iniFile(CString iniFilePath, CString section, CString var, CString wrtVal)
{
    WritePrivateProfileString(section, var, wrtVal, iniFilePath);
}

 

# 단위 분석

- int main

int main(void)
{
    TCHAR tExePath[256];
    GetModuleFileName(NULL, tExePath, sizeof(TCHAR)*256);
    CString csExePath(tExePath);

    CString iniFilePath = csExePath.Left(csExePath.ReverseFind('\\')) + L"\\test.ini";
    ini2para(iniFilePath);

    para2ini(iniFilePath);
}
  • GetModuleFileName 함수는 프로젝트의 실행파일 경로를 반환합니다.
  • 실행파일 경로와 .ini 파일명을 조합하여 iniFilePath 변수에 저장합니다.
  • .ini 파일의 경로가 저장된 변수(iniFilePath)로 통해 파일에 저장하거나 불러올 수 있습니다.

- ini2para

void ini2para(CString iniFilePath)
{
    int count = read_iniFile(iniFilePath, L"TEST", L"count");

    printf("read count val = %d\n", count);
}
  • 매개변수
    - CString iniFilePath = 읽을 파일 경로
  • ini2para 함수는 read_iniFile( )을 호출하여 iniFilePath 경로로 파일을 열어 데이터를 불러오는(read) 함수.

- read_iniFile

int read_iniFile(CString iniFilePath, CString section, CString var)
{
    TCHAR tReadVal[1024];
    GetPrivateProfileString(section, var, NULL, tReadVal, 32, iniFilePath);
	
    return _ttoi(tReadVal);
}
  • 매개변수
    - CString iniFilePath = 읽을 파일 경로
    - CString section = 섹션 이름
    - CString var = 섹션에 속한 변수 이름
  • GetPrivateProfileString(...)을 호출하여 iniFilePath 경로에 있는 파일을 열어 section 에서
    var 변수의 값을 32길이만큼 tReadVal 로 값을 반환.

- para2ini

void para2ini(CString iniFilePath)
{
    write_iniFile(iniFilePath, L"TEST", L"count", L"999");
}
  • 매개변수
    - CString iniFilePath = 읽을 파일 경로
  • para2ini 함수는 write_iniFile( )을 호출하여 iniFilePath 경로로 파일을 열어 데이터를 쓰는(write) 함수.

- write_iniFile

void write_iniFile(CString iniFilePath, CString section, CString var, CString wrtVal)
{
    WritePrivateProfileString(section, var, wrtVal, iniFilePath);
}
  • 매개변수
    - CString iniFilePath = 읽을 파일 경로
    - CString section = 섹션 이름
    - CString var = 섹션에 속한 변수 이름
    - CString wrtVal = 섹션의 변수에 저장할 값
  • WritePrivateProfileString(...)을 호출하여 iniFilePath 경로에 있는 파일을 열어 section 에서
    var 변수에 wrtVal 변수의 값을 쓰는 함수. (var = wrtVal)

 


감사합니다.

 

잘못된 정보나 오타 및 수정사항이 있을 경우 댓글로 달아주시면 감사하겠습니다. 

 


반응형

+ Recent posts