C#에서 JSON 데이터를 다룰 때 가장 많이 사용하는 Newtonsoft.JSON 사용하는 방법에 대해 잘 정리된 블로그이다.


https://devstarsj.github.io/2016/06/12/CSharp.NewtonJSON/



MFC에서 CString 문자열을 cout을 통해서 콘솔 창에 출력하는 방법


간단한 이야기 같으나 멋모르고 달려들다간 간단하지 않다는 걸 깨닫게 된다는게 문제.


CString msg = _T("");

msg += "::_TrackMouseEvent()가 WM_MOUSELEAVE 메시지를 발생 시켰군";

msg += "\n현재의 클라이언트 뷰의 자식 윈도우의 영역을 빠져~~~ 나갈 때~~ 발생시키는 메시지이다.";


//wcout << (const wchar_t*)msg << endl; //이건 띄워쓰기 뒷 부분은 안 나옴

cout << (CString)msg << endl;


위의 코드를 실행하면 cout을 출력하는 부분에서 msg에 대한 주소 값만 달랑 출력하고 끝난다.

0078F488


wcout << (const wchar_t*)msg << endl 

이 방법을 사용해 보면 문자열 내용의 첫 번째 띄워쓰기 뒷 부분은 또 나오질 않는다.


해법은 

프로젝트명 - 마우스 우 클릭 - Properties - Configuration Property -

General - Character set을 Multi-Byte character set으로 설정해 줘야 가능하다.


이렇게 설정하고 나면 cout 대신에 printf()를 이용해도 된다.

참고로 printf()와 cout은 전자가 속도에서 훨씬 빠르다는 것.


printf("%s", msg);  //가능



MFC에서 두 개의 문자열 합치기


자바, C#, python 등의 언어들에서 2개의 문자열을 합치는 것은 간단하고 고민할 필요가 없는 작업이다.

그러나 MFC에서는 자바와 같은 언어들에서 하던 방법으로는 안통한다.

편리한 언어들에 비해서는 좀 불편하긴 하지만 다음과 같은 방법을 사용해서 처리할 수 있다.


CString msg1, msg2, msg3;


msg1 = "여기는 메시지 맵과 메시지 핸들러 함수를 연결하는 방식이 아닌 Win32방식으로 처리해 봄";

msg2 = "\n여기서 이렇게 처리를 해도 메시지 맵과 연결된 메시지 핸들러 함수도 동일하게 처리가 된다.";

msg3 = msg1 + msg2;


MessageBox(msg3);



Visual Studio 2010의 Dark color theme 적용하기


Visual Studio 2017의 경우는 코드 편집창을 Dark로 변경하는 일이 아주 쉬우나 Visual Studi 2010의 경우는 해당 기능이 제공되지 않는 것 같다.

그렇다고 강렬한 흰색의 압박에 대해 소중한 눈을 방치해 둘수도 없는 노릇이기에 방법을 정리해 본다.


먼저 아래 사이트에서 자신이 원하는 셋팅 파일을 다운로드 받는다.


https://studiostyl.es/


필자의 경우는 아래 두 개를 보통 사용한다.

vs2017.vssettings

wekeroad-ink.vssettings


위의 환경 설정 파일을 다운로드 받았다면 


도구(Tools) - 설정 가져오기 및 내보내기(Import and Settings) - No, just import new settings, overwriting my current settings 항목 선태 - Browser 버튼 클릭하여 저장된 *.vssettings 파일 가져오기 - Finish







이 후에 글자 크기가 너무 작다면 

도구(Tools) - Options - Environment - Fonts and Colors에서 원하는 크기로 조정하면 된다.




동일 PC의 Windows에서 동일 PC에 설치된 Vitrualbox의 Ubuntu 간에 ping이 안될때


※ 전제조건 : 동일 Windows PC상에 Virtualbox가 설치되어 있다고 가정한다.


소켓통신 프로그램을 개발하거나 이더넷 통신... 등등을 개발하다보면 실제 장비와 하기 전에 테스트 차원에서 Virtualbox의 리눅스와 PC간에 통신 프로그램을 개발하는 경우들이 있다.

이때 통신이 정상적인 상태인지를 체크하기 위해 보통은 ping으로 테스트하는 경우가 있다.


아래와 같이 리눅스의 터미널 창에서 PC쪽으로 ping을 날리거나 반대로 PC의 DOS창(커맨더 창)에서 Virtualbox 쪽으로 ping을 날림을 통해서 네트워크 연결 상태를 체크하게 된다.


ping 192.168.211.105


이러한 상황에서 

① 양방향 모두 ping 전송 실패하거나

② PC에서 Virtualbox 쪽으로는 가능하나 그 반대는 안되는 경우

에 대해서 살펴본다.


다른 네트워크 설정 상태가 정상임에도 위 ①의 경우가 발생한다면 우선적으로 Virtualbox의 네트워크 설정 상태를 NAT에서 브릿지 어댑터로 변경해 주어야 한다.

아래 그림과 같이 설정 - 네트워크 - 어댑터1 - 다음에 연결 항목에 있는 NAT를 브릿지 어댑터로 변경한 후 Virtualbox를 재시작한다.



위 ②번의 경우는 아마도 리눅스(여기서는 Ubuntu)의 네트워크 환경 설정 중에서 gateway를 잘못 설정했을 경우에 발생하는 현상이다. 그러나 네트워크의 경우는 워낙 다양한 변수들이 있기에 항상 정답이 될수는 없다.

이 경우 gateway를 올바로 설정하기 위해서는 우선 gateway의 ip 주소를 알아야 한다.

PC의 DOS창을 열어서 ipconfig 명령을 실행하면 아래와 같은 정보를 얻었다면 여기서 "기본 게이트웨이"에 있는 ip를 Ubuntu의 gateway로 설정해 주면 된다.


   연결별 DNS 접미사. . . . :

   링크-로컬 IPv6 주소 . . . . : fe80::84aa:fa63:4a5f:23a2%12

   IPv4 주소 . . . . . . . . . : 192.168.219.186

   서브넷 마스크 . . . . . . . : 255.255.255.0

   기본 게이트웨이 . . . . . . : 192.168.219.1


/etc/network/ 디렉토리 아래에 interfaces라는 파일을 열어서

아래 예시와 같이 gateway의 값을 지정한 후 파일을 저장한다.


auto enp0s3

iface enp0s3 inet static

address 192.168.219.115

netmask 255.255.255.0

gateway 192.168.219.1

dns-nameserver 8.8.8.8 8.8.4.4


이후 다음 명령어로 네트워크 장비를 재시작한다.


ip addr flush enp0s3 && /etc/init.d/networking restart



python에서 리눅스 shell command를 이용하여 특정 프로그램의 실행 여부 파악하기


리눅스에서 특정 프로그램의 실행 여부를 파악할 때 터미널 창에서 ps 명령어를 이용해서 대개는 확인하게 된다. SocServer라는 이름을 가진 프로그램이 현재 실행중인지 파악할려면 아래와 같이 한다.


ps -elf | grep SocServer*


이렇게 되면 다음과 같은 정보가 보인다면 해당 프로그램은 실행 중이라는 뜻이다.


0 S root     14851  1812  0  80   0 -  8931 inet_c 16:53 pts/18   00:00:00 python /home/joe/PyCharmProj/SocServer.py


여기서 4번째 column의 값 14851이 SocServer.py의 실행 process id이다. 즉 특정 프로그램의 process가 존재하는지를 통해서 해당 프로그램의 실행 여부를 파악할수 있는 것이다.


이 프로그램의 실행을 강제 종료 시킬려면 다음과 같이 하게 될 것이다.


kill -9 14851


위의 기능과 같은 기능을 하되 보다 단순한 정보를 보여주는 shell command가 있는데 pgrep이다.


pgrep -lf SocServer*


를 하면 다음과 같은 보다 간단한 정보를 나타내준다. 


14851 python


이렇게 간단한 정보를 활용하면 파이썬 상에서 코딩하기가 보다 수월해 진다.

아래는 파이썬에서의 특정 프로그램 실행 여부를 확인하는 코드이다.

이를 위해서는 os와 subprocess 파이썬 모듈을 import 시켜야 한다.



import os

import subprocess


# 이미 실행 중인 process가 있으면 다시 실행되지 않도록 하기 위해

# 실행되는 process가 없으면 0을 반환, 있으면 1을 반환

socSrvProc = subprocess.check_output("pgrep -lf SocServer* | wc -l", shell=True)

print 'socSrvProc : ', socSrvProc


if int(socSrvProc) == 0 :  # SocServer.py가 기존 돌아가고 있는 것이 없으면

    # PC의 C# .DLL library와 소켓 통신을 위한 별도의 프로그램.

    # SocServer.py가 서버 역할 C# .DLL library가 client 역할

    os.system("python /home/joe/PyCharmProj/SocServer.py &")


    print 'SocServer.py를 실행했습니다. 서버 소켓 준비됨'

else :

    print 'SocServer는 이미 실행 중입니다.'



python에서 리눅스 쉘 명령어(shell command)를 이용하여 자기 IP 알아내기


소켓 통신 등의 경우 특히 서버 역할을 하는 경우 자기 IP를 스스로 알아내는 코드기 필요하다.

검색해 보면 파이썬에서 이를 알아내는 코드가 소개되어 있는데 다음과 같이


socket.gethostbyname(socket.gethostname())

socket.gethostbyaddr(socket.gethostname())

socket.gethostbyname_ex(socket.gethostname())


127.0.0.1인 loop back IP 값만 반환해 준다.

리눅스의 경우는 파이썬에서 shell command를 적절히 사용하면 여러모로 간한하게 문제를 해결할수 있다.


우선 socket과 subprocess 모듈을 import해야 한다.


import socket

import subprocess


그리고 리눅스 shell command중에서 IP를 확인하는 명령어들이 몇가지 있으나 단지 IP 정보만이 아닌 여러가지 부가적인 정보를 같이 보여주기 때문에 사용하기 용이하지 않다.

대표적으로 ifconfig같은 경우 아래와 같은 정보를 보여준다.


enp0s3    Link encap:Ethernet  HWaddr 08:00:27:ff:a4:58  

          inet addr:192.168.0.150  Bcast:192.168.0.255  Mask:255.255.255.0

          inet6 addr: fe80::c33f:ad86:8225:3597/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:62078 errors:0 dropped:0 overruns:0 frame:0

          TX packets:56852 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000 

          RX bytes:17715562 (17.7 MB)  TX bytes:44145423 (44.1 MB)


lo        Link encap:Local Loopback  

          inet addr:127.0.0.1  Mask:255.0.0.0

          inet6 addr: ::1/128 Scope:Host

          UP LOOPBACK RUNNING  MTU:65536  Metric:1

          RX packets:108 errors:0 dropped:0 overruns:0 frame:0

          TX packets:108 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000 

          RX bytes:14178 (14.1 KB)  TX bytes:14178 (14.1 KB)


우리가 필요로하는 것은 단지 자신의 IP만 알면 되는데 이 경우 사용할수 있는 명령어가 hostname이라는 shell command이다.


hostname -I를 실행하면 192.168.0.150과 같은 자신의 IP를 알아낼수 있다.

아래는 코드조각이다.


import socket

import subprocess


myIP = subprocess.check_output("hostname -I", shell=True)

print 'My IP : ', myIP



python Tkinter GUI 프로그램에서 lambda를 이용한 버튼 이벤트 처리


코드에서 막바로 lambda를 이용한 버튼 클릭 이벤트에 대해서 살펴보자.

아래는 코드이다.

프로그램 실행하면 다음과 같은 윈도우 창이 뜨게 된다.




#-*- coding:utf-8 -*-


# 파이썬 GUI용 툴킷 Tkinter를 import

from Tkinter import *


# Tkinter 윈도우 객체 생성

root = Tk()


# (가로 x 세로 + x위치좌표 + y위치좌표)

root.geometry("500x300+300+200")


def callback(number):

    print "Button-", number


print 'b1'

# btn1 버튼 클릭시 실행할 메소드는 callback()이고

# 이 메소드로 넘길 paramter 값은 111이다.

# 따라서 btn1 버튼 클릭시 아래 내용 출력된다.

# Button- 111

btn1 = Button(text="One", command=lambda: callback(111))

btn1.configure(font=("Consolas", 15), width=20)

btn1.pack(pady=7)


print 'b2'

btn2 = Button(text="Two", command=lambda: callback(222))

btn2.configure(font=("Consolas", 15), width=20)

btn2.pack(pady=7)


print 'b3'

btn3 = Button(text="Three", command=lambda: callback(333))

btn3.configure(font=("Consolas", 15), width=20)

btn3.pack(pady=7)


# Tkinter 윈도우 화면에 표시

root.mainloop()



C#에서 만든 .DLL 라이브러리를 MFC(C++)에서 사용할려면 .tlb 파일을 생성 및 윈도우즈 레지스트리에 등록하는 과정이 필요하다.

이를 위해서는 MS 제공 RegAsm.exe라는 프로그램을 이용해서 처리를 하게 될텐데(자세한 정보는 여기를 클릭) 이를 위해서 Developer Command Prompt for VS 2017라는 일종의 커맨더 창에서 작업을 하게된다.

이는 개발자가 개발 단계에서는 문제가 되지 않으나 개발된 프로그램을 일반 사용자에게 배포하게 될때는 일반 사용자가 이 작업을 할수는 없는 것이다.

따라서 프로그램상에서 .DLL로부터 .tlb 생성 및 레지스트리 등록을 처리해야 할 것이다.


본 포스트는 C# 코드상에서 이 두 가지 작업을 수행하는 방법에 대해 정리하고자 한다.

C#에서 외부 실행 파일을 실행하는 것 자체는 그렇게 어려운 작업은 아니나 문제는 레지스트리에 뭔가를 쓰게 되는 일은 시스템의 보안상 간단하게 처리되어질수는 없는 일이기에 코드상에서 처리하는 일에 복잡성이 발생하게 된다.

이러한 상황 가운데서 위 2가지 작업을 프로그램적으로 어떻게 처리할수 있는지를 살피고자 한다.


핵심은 프로그램 자체가 '관리자 권한'으로 실행되는 프로그램이어야 한다는 것이다. 이렇게 되어야 코드를 통해서 레지스트리 등록이 가능해 진다.


(1) 관리자 권한으로 실행되는 프로그램 만들기

Visual Studio 2017을 기준으로 설명하면 '솔루션 탐색기' 탭에서 해당 프로젝트 이름위에 마우스 우 클릭 ⇒ 속성 ⇒ 보안 ⇒ "ClickOnce 보안 설정 사용"을 체크 ⇒ 이 상태를 저장(Ctrl-S)



이상의 작업을 거치면 '솔루션 탐색기' 탭의 프로젝트 명 아래의 Properties 항목 아랫쪽에 app.manifest라는 파일이 생성이 된다.

이 파일의 설정 값을 조정함을 통해서 현재의 프로그램이 관리자 권한으로 실행되는 프로그램으로 설정된다.



아래 그림의 노랑색 밑줄친 부분의 level의 값 asInvoker를 requireAdministrator로 변경을 해 준 후 저장을 한다.



Visual Studio 2017을 종료 후 '관리자 권한'으로 새로 시작한다.

(그렇지 않고 현재 상태에서 프로그램을 디버깅(실행)하면 "다른 자격 증명을 사용하여 다시 시작"할 것인지 묻는 창이 뜬다. 이 창이 의미하는 것은 Visual Studio 2017을 관리자 권한으로 다시 실행하겠느냐는 뜻이다.)


프로그램을 디버깅(실행)하면 현재 프로그램의 .exe 실행 파일이 생성이 되고 이 실행 파일은 매 실행시마다 관리자 권한으로 실행 여부를 사용자에게 묻게 된다.


(2) .tlb 파일 생성 및 윈도우즈 레지스트리 등록하는 소스 코드


using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Text;

using System.Threading.Tasks;


namespace RegisterTLB

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("This program is registering .TLB to Windows registry.");


            var proc = new ProcessStartInfo();


            // .dll을 이용해서 .tlb생성 및 레지스트리 등록 명령어

            // regasm의 사용법은 DOS창(커맨더 창)에서 regasm /?을 하면 

            // regasm을 아래와같이 이 파일의 경로를 표시하지 않으면 현재의 프로그램의 실행 파일과 같은 위치에

            // regasm.exe가 있어야 된다.

            string mCmd = "regasm EthernetClientLib.dll /tlb:EthernetClientLib.tlb";

            proc.UseShellExecute = true;


            //아래 경로에 .DLL가 있어야하고 .tlb가 이 위치에 생성이 되고 regasm.exe도 이 위치에서

            //작업을 하게된다.

            proc.WorkingDirectory = @"D:\Joe\CSharp\EthernetClientLib\EthernetClientLib\bin\Debug";


            //위의 regasm EthernetClientLib.dll /tlb:EthernetClientLib.tlb를 실행시킬 명령어

            proc.FileName = "cmd.exe";


            //아래 속성의 runas 자체가 관리자 권한으로 실행시키겠다는 설정값이다.

            proc.Verb = "runas";

            proc.Arguments = "/C " + mCmd;

            proc.WindowStyle = ProcessWindowStyle.Hidden;

            Process rt = Process.Start(proc);


            Debug.WriteLine("##### .tlb 생성 및 레지스트리 등록을 마쳤습니다.");

        }

    }

}



C# .dll library에서 MessageBox 사용하기(메시지 창 띄우기)


C#의 프로젝트를 클래스 라이브러리(.dll 라이브러리)로 생성하면 기본적으로 MessageBox를 띄울수 없다.

그런데 C# .dll 라이브러리 단에서 굳이 메시지 창을 띄워야 할 경우가 있을 것이다. 그게 여러모로 편리할 것이다.

이런 경우에 대한 해법이다.


프로젝트 명에 우측 마우스 - 추가 - 참조 - 어셈블리 - 프레임워크 - System.Windows.Forms를 체크해 주면

아래 클래스가 자동으로 using에 포함된다.

만일 자동으로 추가되지 않으면 아래 내용을 직접 타이핑해서 추가해 주면 된다.


using System.Windows.Forms;





이후에 필요한 곳에서 아래와 같이 사용하면 되겠다.


MessageBox.Show("해당하는 이미지가 없습니다.", "적당한 제목");


(C# 프로그램을 .dll Library로 만드는 방법은 여기를 클릭)


+ Recent posts