2010년 10월 22일 금요일

알고 있어야 도움이 되는 몇가지 API들

거의 모든 위도 애플리케이션에는 파일을 다루는 로직이 들어가게 된다. 미리 설정된 환경설정 파일을 읽어 내거나, 작업하기 위한 데이터가 있는 파일을 읽기도 하고, 현재 애플리케이션의 환경 설정 파일을 보조 저장장치에 저장하거나, 작업하고 있는 파일 내용을 저장하는 등의 동적은 기본적인 애플리케이션의 기능이다.

 

  보통 이러한 작업은 기존에 재활용을 위하여 잘 정의를 해 놓은 MFC CFile과 같은 클래스를 이용하지만, 기존 준비해 놓은 클래스에는 없는 기능을 구현하고 싶거나, 클래스 기능을 확장하고 싶을 때, 혹은 순수 API 환경에서 새로 기능을 구현해야 할 때가 있다. 이럴 경우 파일 관련 유틸리티 클래스를 만들게 되는데, 의외로 이러한 유틸리티 클래스를 만드는 부분에서 문제 있는 코드를 많이 만들어 내게 된다. 예를 들어 디렉토리 인지 판단하는 IsDirectory() 함수를 다음과 같이 정의 했다고 가정해 보자.

 

BOOL IsDirectory(const TCHAR* path) {

WIN32_FIND_DATA findFileData;

HANDLE findFile = FindFirstFile(path, &findFileData);

FindClose(findFile);

return (BOOL)(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);

}

 

  아마 xp가 설치된 일반적인 개발 머신의 환경에서는 잘 동작하기 때문에 잘 동작하는 코드라 생각할 것이다. 그러나 이 함수에는 몇 가지 오류를 일으킬 수 있다.

 

  FindFirstFile의 리턴값을 INVALID_HANDLE_VALUE 인지 체크 하는 부분이 빠져 있는데, 결과적으로 이 함수가 포함된채 릴리즈 되게 되면, xp가 설치가 된 어떤 깨끗한 PC에서는 FALSE가 리턴되어야 할 상황에서TRUE가 리턴 되기도 하고, 어떤 2000 서버와 같은 환경에서는 익셉션이 나서 애플리케이션이 비정상 종료 되는 경우도 있으며, 익셉션 처리가 되어 있는 경우 IsDirectory()를 이용하는 루틴의 수행이 중간에 종료가 되기도 한다.

 

  물론 이러한 문제 있는 코드를 만들지 않도록 함수를 확실히 검증 하고 사용 하는 것이 중요하고, 리턴 값을 철저히 검사 하는 등의 기본을 지키는 코딩을 습관화 하는 것이 중요하다. 그러나 대부분 일정에 대한 데드라인이 있는 상태에서 막히는 부분을 간단히 검색해서 당장의 문제를 해결 하다 보면, 위의 오류가 포함된 것 같은 코딩을 하기가 쉽다.

 

  이러한 기본적인 기능을 하는 함수들은 API 형태로 제공해 주는 것들이 많다. 특히 path에 관련된 API들은 API prefex Path가 붙어 있으므로, Shell Path와 관련된 기능이 필요하다면, 먼저 개발자 커뮤니티를 검색하기 전에 MSDN Index Path로 검색해 보면 유용하면서 검증된 API를 찾을 수 있을 것이다.

 

Shell Path와 관련된 유용한 API중 일부 몇 가지 정리해 보면 다음과 같다

 

 

함 수 명

 

 

PathAddBackslash

c:\path1

c:\path1\

PathBuildRoot

0

A:\

PathCanonicalize

c:\path1\..\.\path1

c:\path1

PathCompactPath

c:\path1\path2\path3\file.txt

c:\path1\...\file.txt

PathFileExists

c:\path1\file.txt

파일의존재유무[T/F]

PathFindFileName

c:\path1\path2\file.txt

file.txt

PathIsDirectory

c:\path1\path2

디렉토리유무[T/F]

PathIsfileSpec

file.txt

순수파일이름인지[T/F]

PathMakePretty

C:\PATH1\FILE.TXT

C:\path1\file.txt

PathIsNetworkPath

\\YHKim\path1\file.txt

네트워크경로인지[T/F]

PathIsRoot

c:\

루트경로인지유무[T/F]

PathIsSystemFolder

c:\windows\System32

시스템폴더인지유무[T/F]

PathRemoveBackslash

c:\path1\path2\

c:\path1\path2

PathRemoveBlanks

c:\path1\path2

c:\path1\path2

PathRemoveExtension

c:\path1\path2\file.txt

c:\path1\path2\file

PathRemoveFileSpec

c:\path1\path2\file.txt

c:\path1\path2

PathRenameExtension

c:\path1\path2\file.txt

c:\path1\path2\file.changed

PathStripPath

c:\path1\path2\file.txt

file.txt

 

API를 정리해 놓게 되면, 마치 요가를 해서 관절이 유연해 지는 것과 같은 느낌을 받는다. 요가를 연습하면 유연하지 않은 사람보다 팔과 다리를 움직일 수 있는 범위가 넓어 지듯이, API를 정리해 놓으면 애플리케이션을 통하여 상상력을 발휘할 수 있는 범위가, 학습한 만큼의 관절의 활동 범위처럼 넓어 지게 된다.

 

관련된 참고할 만한 MSDN Resource

Shell Function들 중 일부 함수들

http://msdn2.microsoft.com/en-us/library/bb776426(VS.85).aspx

Shell Lightweight Utility Functions Path와 관련된 함수들

http://msdn2.microsoft.com/en-us/library/bb773559(VS.85).aspx

User Profiles Function Path를 얻어 오는데 관련된 함수들

http://msdn2.microsoft.com/en-us/library/aa375109(VS.85).aspx

 

 

ps. Path가 등록이된 파일을 찾고 싶다면, SearchPath를 이용하면 FullPath가 넘어 온다.

 

질문) 클라이언트 컴퓨터에 설치된 firefox의 경로를 찾고 싶은데 어떻게 하지? Firefox가 써 놓은 레지스터리값를 뒤져볼까? firefox의 기본 설치 경로에 exe 파일을 createfile해서 판단할까?

답 예시) SearchPath를 이용하셔서 FullPath를 얻으시고, 얻은 FullPath PathFileExists로 검증하시면 됩니다

댓글 1개: