Create TOC

2012년 8월 22일

Windows/디스크 정리 도구를 자동화

원문에서는 XP만 다루고 있지만 Windows 7에서도 잘 작동한다.

우선 아래 명령으로 자동으로 청소할 항목을 선택한다.

cleanmgr /SAGESET:1

여기서 1은 원하는 숫자를 사용하면 된다. 청소할 항목을 지정했으면, 아래 명령으로 지정한 항목을 청소시킬 수 있다.

cleanmgr /SAGERUN:1

Linux/awk를 사용해서 숫자들의 합 세기

아래와 같은 csv 파일이 있다고 가정한다.

a,1
b,2
c,3
d,4
e,5

위 파일에서 두 번째 열의 숫자를 모두 합하고 싶다면 아래와 같이 하면 된다.

cat test.csv | awk -F "," '{sum += $2} END {print sum}'

Linux/특정 확장자를 가진 파일의 line 수 세기

findwc를 사용하면 된다.

wc --lines `find ./ -type f \( -name "*.c" -or -name "*.cpp" -or -name "*.asm" -name "*.h" \)`

2012년 8월 14일

Windows8/제품 키를 변경해서 인증 받기

이미 등록된 제품 번호를 변경하고 다시 인증을 받는 방법을 설명한다.

관리자 권한으로 cmd 창을 열고 아래 명령을 차례대로 입력한다.

cscript %windir%\system32\slmgr.vbs /upk
cscript %windir%\system32\slmgr.vbs /ipk 제품번호
cscript %windir%\system32\slmgr.vbs /ato
제품 번호는 XXXXX-XXXXX-XXXXX-XXXXX-XXXXX 형식을 사용하면 된다.

2012년 8월 13일

Python/ctypes in Win32

ctypes를 이용해 Win32 환경에서 작업하는 예제 기록.

자료구조

ctypes vs Win32

ctypes.wintypes를 참고한다.

배열

WCHAR [1000]의 배열을 선언한다고하면

FileNameType = c_wchar * 1000
a = FileNameType()

익명 구조체/공용체 선언

SYSTEM_INFO 구조체는 아래와 같이 역명 구조체와 공용체를 가지고 있다.

typedef struct _SYSTEM_INFO {
	union {
		DWORD  dwOemId;
		struct {
			WORD wProcessorArchitecture;
			WORD wReserved;
		};
	};
	DWORD     dwPageSize;
	LPVOID    lpMinimumApplicationAddress;
	LPVOID    lpMaximumApplicationAddress;
	DWORD_PTR dwActiveProcessorMask;
	DWORD     dwNumberOfProcessors;
	DWORD     dwProcessorType;
	DWORD     dwAllocationGranularity;
	WORD      wProcessorLevel;
	WORD      wProcessorRevision;
} SYSTEM_INFO;

이 구조체를 ctypes로 표시하면 아래와 같다.

class _Noname1(ctypes.Structure):
    _fields_ = [("wProcessorArchitecture", ctypes.c_ushort),
                ("wReserved", ctypes.c_short)]


class _Noname2(ctypes.Union):
    _anonymous_ = ("s",)
    _fields_ = [('dwOemId', ctypes.c_ulong),
                ('s', _Noname1)]


class SYSTEM_INFO(ctypes.Structure):
    _anonymous_ = ("u",)
    _fields_ = [("u", _Noname2),
                ("dwPageSize", ctypes.c_ulong),
                ("lpMinimumApplicationAddress", ctypes.c_void_p),
                ("lpMaximumApplicationAddress", ctypes.c_void_p),
                ("dwActiveProcessorMask", ctypes.c_ulong),  # 64 bit에서는 c_longlong이 되어야 한다.
                ("dwNumberOfProcessors", ctypes.c_ulong),
                ("dwProcessorType", ctypes.c_ulong),
                ("dwAllocationGranularity", ctypes.c_ulong),
                ("wProcessorLevel", ctypes.c_ushort),
                ("wProcessorRevision", ctypes.c_ushort)]

pointer type 선언

위에서 선언한 SYSTEM_INFO에 대한 pointer type으로 LPSYSTEM_INFO을 선언한다고 하면

LPSYSTEM_INFO = ctypes.POINTER(SYSTEM_INFO)

ctypes.LP_c_char를 문자열로 변환

ctypes.LP_c_charctypes.c_char_p로 형변환하면 된다.

ctypes.cast(ctypes.LP_c_char 객체, ctypes.c_char_p).value

함수 호출

Win32 API 호출

ctypes.windll뒤에 원하는 dll 모듈과 함수를 사용하면 된다. 예를 들어 kernel32GetsystemInfo함수를 호출한다면 아래와 같이 호출할 수 있다.

ctypes.windll.kernel32.GetsystemInfo( ... )

DLL 함수 호출

test1.dllvoid __cdecl testfunction1() 함수를 호출한다고 하면

test1 = ctypes.CDLL('test1.dll')
if test1:
	test1.testfunction1()

함수 인자로 pointer 전달

si = SYSTEM_INFO()
ctypes.windll.kernel32.GetSystemInfo(ctypes.byref(si))

함수 인자로 string buffer 전달

buf = ctypes.create_unicode_buffer(4096)
r = ctypes.windll.kernel32.GetWindowsDirectoryW(buf, 4096)
if r > 0:
	print buf.value

함수 반환값 검사

함수 객체의 errcheck를 지정하면 함수의 반환값 검사를 모아서 할 수 있다. 예를 들어 test2.dllBOOL __cdecl testfunction2() 함수에 대해서 코드를 작성해보면 아래와 같다.

>def checkBOOL(result, function, args):
    if result == 0:
		raise ctypes.WinError()
	return args

test2 = ctypes.CDLL('test2.dll')
test2.testfunction2.errcheck = checkBOOL

test2.testfunction2()  # 함수 호출이 끝나면 바로 checkBOOL 함수가 호출되서 반환값 검사를 할 수 있다.

명시적인 함수 인자 지정

함수 객체의 argtypes를 이용해서 함수의 인자를 명시적으로 지정할 수 있다. 예를 들어 test3.dllBOOL __cdecl testfunction3(LPCWSTR, LPBOOL)에 대해서 코드를 작성해보면 아래와 같다.

test3 = ctypes.CDLL('test3.dll')
test3.testfunction3.argtypes = [ctypes.c_wchar_p, ctypes.POINTER(ctypes.c_long)]

b = ctypes.c_long()
r = test3.testfunction3(u"hello, world!", ctype.byref(b))

명시적인 함수 반환형 지정

함수 객체의 restype을 시용해서 함수의 반환형을 명시적으로 지정할 수 있다(함수 반환형이 void라면 None을 사용한다). 예를 들어 test4.dllHANDLE __cdecl testfunction4()에 대해서 코드를 작성해보면 아래와 같다.

test4 = ctypes.CDLL('test4.dll')
test4.testfunction4.restype = ctypes.c_void_p

h = test4.testfunction4()

callback 함수

callback 함수 형식에 따라 ctypes.CFUNCTYPE 또는 ctypes.WINFUNCTYPE을 사용해서 callback 함수 형을 만들면 된다.

CFUNCTYPE

python 문서에 나온 예제를 Win32에 맞게 변형했다.

CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))


def py_cmp_func(a, b):
    print 'py_cmp_func', a[0], b[0]
    return 0

cmp_func = CMPFUNC(py_cmp_func)

IntArray5 = ctypes.c_int * 5
ia = IntArray5(5, 1, 7, 33, 99)
qsort = ctypes.windll.msvcrt.qsort
qsort.restype = None
qsort(ia, len(ia), ctypes.sizeof(ctypes.c_int), cmp_func)

WINFUNCTYPE

LF_FACESIZE = 32
LF_FULLFACESIZE = 64


class LOGFONT(ctypes.Structure):
    _fields_ = [
        ('lfHeight', ctypes.c_long),
        ('lfWidth', ctypes.c_long),
        ('lfEscapement', ctypes.c_long),
        ('lfOrientation', ctypes.c_long),
        ('lfWeight', ctypes.c_long),
        ('lfItalic', ctypes.c_byte),
        ('lfUnderline', ctypes.c_byte),
        ('lfStrikeOut', ctypes.c_byte),
        ('lfCharSet', ctypes.c_byte),
        ('lfOutPrecision', ctypes.c_byte),
        ('lfClipPrecision', ctypes.c_byte),
        ('lfQuality', ctypes.c_byte),
        ('lfPitchAndFamily', ctypes.c_byte),
        ('lfFaceName', ctypes.c_wchar * LF_FACESIZE)]
PLOGFONT = ctypes.POINTER(LOGFONT)


class ENUMLOGFONT(ctypes.Structure):
    _fields_ = [
        ('elfLogFont', LOGFONT),
        ('elfFullName', ctypes.c_wchar * LF_FULLFACESIZE),
        ('elfStyle', ctypes.c_wchar * LF_FACESIZE)]
PENUMLOGFONT = ctypes.POINTER(ENUMLOGFONT)


if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
    LPARAM = ctypes.c_long
elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
    LPARAM = ctypes.c_longlong

#int CALLBACK EnumFontFamProc(ENUMLOGFONT *lpelf,__in  NEWTEXTMETRIC *lpntm, DWORD FontType, LPARAM lParam;
EnumFontFamProc = ctypes.WINFUNCTYPE(ctypes.c_int, PENUMLOGFONT, ctypes.c_void_p, ctypes.c_long, LPARAM)


def py_enum_font_fam_proc(lpelf, lpntm, FontType, lparam):
    print 'py_enum_font_fam_proc', lpelf.contents.elfFullName
    return 1

enum_font_proc = EnumFontFamProc(py_enum_font_fam_proc)

EnumFontFamilies = ctypes.windll.gdi32.EnumFontFamiliesW
hdc = ctypes.windll.user32.GetDC(0)
EnumFontFamilies(hdc, 0, enum_font_proc, 0)
ctypes.windll.user32.ReleaseDC(hdc)

2012년 8월 11일

cygwin/Windows 개발을 위한 Makefile template

cygwin에서 Windows 프로그램 개발을 위한 Makefile template.

BASECFLAGS = -DUNICODE -D_UNICODE -DWIN32 -D_WIN32 -Wall -Wextra -ffunction-sections -fdata-sections
CXXFLAGS = -fno-rtti -fno-exceptions

ifdef debug
	OPTFLAGS = -g -DDEBUG -Wall -Wextra -Wfloat-equal -Wunreachable-code
else
	OPTFLAGS = -Os -s -DNDEBUG
endif

ifdef x64
	MINGWPREFIX = x86_64-w64-mingw32
	CFLAGS = $(BASECFLAGS) $(OPTFLAGS) -DWIN64 -D_WIN64
else
	MINGWPREFIX = i686-pc-mingw32
	CFLAGS = $(BASECFLAGS) $(OPTFLAGS)
endif
LDFLAGS = -Wl,--gc-sections -mwindows -mno-cygwin

CC = $(MINGWPREFIX)-gcc
CXX = $(MINGWPREFIX)-g++
RES = $(MINGWPREFIX)-windres

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

%.o: %.cpp
	$(CXX) $(CFLAGS) $(CXXFLAGS) -c $< -o $@

%.res.o: %.rc
	$(RES) -i $< -o $@

Makefile은 아래와 같이 사용할 수 있다.

디버그 빌드시

$ make debug=1

x64 빌드시

$ make x64=1