VS2005에서 (C#) 디버깅 시 “잘 못된 바인딩 핸들입니다”라는 메시지로 디버깅이 안될 때는 터미널 서비스를 시작

5 Comments

간단히 C#으로 할 것이 있어서 디버깅을 하려는데, (분명 예전엔 잘 되었는데)

아래와 같은 메시지가 출력되었다.
“디버깅을 시작할 수 없습니다. 잘못된 바인딩 핸들입니다”
회원님이 촬영한 debug.
머가 잘 못 된 것인지 아무런 힌트도 없었다.
네이버님을 찾아보니 “Terminal Service”가 시작되지 않아서 문제가 발생한 것이라고 한다.
그래서 관리도구-서비스-터미널 서비스를 시작 시키니 디버깅이 잘 되었다.
원이이 궁금해서 MSDN을 찾아보니 VS2005의 Debugger가 Process Listing을 위해서 Terminal Service를 사용하기 때문이라고 한다.
Ref
[1] [C#].NET 2005에서 디버깅 오류
[2] Error message when you try to run a Visual C# project in the Visual Studio 2005 IDE: “The binding handle is invalid”

[VS2005] error C4335: Mac file format detected 에러에 대해

1 Comment

VS2005이 너무 예민할 것인가? 아니면 (최소한) windows만을 쓰라고 강요하고 싶은 것일까?

컴파일을 하다 만나게 되는 조금은 당황스러운 다음 에러를 보자.

error C4335: Mac file format detected

[MSDN]에서 위 에러를 찾아보면 말 그대로 DOS (‘\r\n’) 나 UNIX (‘\n’)이 아닌 Mac (‘\r’) 파일 형식을 찾았고 이 것을 DOS나 UNIX로 변환해달라고 한다.
찾았으면 내부에서 처리를 해주지… 쩝쩝..

Compiler Warning C4335

Error Message

Mac file format detected: please convert the source file to either DOS or UNIX format

The line termination character of the first line of a source file is Mac style (‘\r’) as opposed to UNIX (‘\n’) or DOS (‘\r\n’).

MSDN 포럼 에서는 관심도 없는 것 같고 주로 open source등에 관련된 곳에서는 위 에러로 기염을 토하는 흔적을 볼 수 있다.

아무튼 해결책은

1. 다음과 같이 4335 warning을 무시하든지

        #pragma warning( disable : 4335 )

2. 코드를 윈도우에서 에디터로 한 번 열어주든지

3. perl/awk/sed 스크립트를 아래와 같이 작성하든지
       
sed -e ‘s/\r/\r\n/g’

4. 여기에 나와있는 것 처럼 프로그램을 하나 찾아서 ‘\r’으로만 개행이되는 것을 찾아서 변환해주면 될 것이다.

[Ref]
Compile error C4335: Mac file format detected
http://www.codeguru.com/forum/archive/index.php/t-408660.html
http://www.mpcforum.com/archive/index.php/t-57494.html

VS2005 솔루션을 릴리즈하거나 SCM으로 관리할 때 지워도 되는 파일들

No Comments

Visual C++ 6.0에서 *.ncb, *.opt 파일 등을 Clear Case에 올렸다가 (Add to Source Control) 프로젝트를 열 때 마다 check-out 을 해 귀찮았던 경험을 누구나 한 번쯤을 해봤을 것이다.

이와 마찬가지로 VS 2005의 solution에서도 코드를 배포하거나 Clear Case나 SVN 등에 코드를 관리하기 위해 서버에 올릴 때 필요 없는 파일들이 있을 것이다.

project1.sln                                     // solution file
project1.vcproj                                // project file
project1.suo                                    // Holds solution options and configuration (삭제 가능)
project1.vcproj.PRO1.Alex.user    // 사용자 설정 (삭제 가능)

위 파일 중 sln과 vcproj 을 제외하고 모두 삭제해도 된다.
(solution file을 다시 열면 모두 자동 생성된다)

[Ref]
Dealing with VS2005 .suo files
VS 2005: very confusing project files and privacy issues!

[Tips] Win32 콘솔 애플리케이션에서 MFC class들을 사용하기

5 Comments

이미 잘 알려진 내용이지만 제 블로그의 검색을 위해 짧게 포스팅합니다.

Visual Studio 6.0에서 Win32 콘솔 애플리케이션 (Console Application)으로 프로젝트를 만들어 표준 C/C++ 라이브러리를 이용할 때 MFC (Microsoft Foundation Class Library)의 클래스들 (e.g. CString, CObList)을 이용하는 방법입니다.

1. CRT (C Run-Time) library를 Multithreaded로 변경

  1. Alt+F7을 누르거나 메뉴의 Project / Setting을 선택해서 “Project Settings” 창을 띄웁니다.
  2. “C/C++” 탭에서 “Category”를 “Code Generation”이라고 선택합니다.
  3. 아래 그림과 같이 “Use run-time library”를 “Debug Multithreaded”로 변경합니다.
    ※ 물론 릴리즈 모드인 경우는 Multithreaded를 선택하겠죠.

MFC 클래스를 위한 헤더 파일들을 포함시켜도 링크 에러가 나는 것은 Win32 console application 프로젝트는 기본적으로 “Single-Threaded” CRT library를 사용해서 멀티스레드를 위한 api 구현이 없기 때문입니다. 그래서 이와 같이 CRT 라이브러리를 변경하는 것입니다.

2. 필요한 헤더 파일 포함

사용할 MFC 클래스를 정의하고 있는 헤더 파일들을 포함합니다.

※ MFC의 헤더 파일과 라이브러리 설명은 Devpia의 이 글을 참고하시면 됩니다.

간단히 많은 것을 포함하는 헤더 파일들만 설명드리면..

Afx.h: MFC를 위한 main header file로 컨테이너를 비롯한 많은 MFC 클래스들을 선언합니다.

Afxtempl.h: CArray등 템플릿을 요하는 클래스들의 선언을 가지고 있습니다.

간단히 CString이나 CObList를 사용하는 경우는 Afx.h를 포함하면 될 것이고

CArry, CList등 템플릿 컨테이너 클래스를 사용할 경우는 Afxtempl.h를 포함하면됩니다.

순서는 Afx.h가 먼저 오는 것이 좋겠죠? (순서가 바뀌어도 컴파일 에러는 나지 않으나…)

GetFileTime 또는 GetFileAttributesEx를 이용한 파일의 최종 수정 시간 구하기

27 Comments

아래 내용은 Wiki에서 최신 내용을 볼 수 있습니다.

  • initial version: 2007.08.21

목차

1 File의 마지막 수정 시간 (last-write time) 얻기
2 GetFileTime() 이용
2.1 Signature
2.2 Discription
2.3 Example
3 GetFileAttributesEx() 이용
3.1 Signature
3.2 Discription
3.3 Example

1 File의 마지막 수정 시간 (last-write time) 얻기 #

어떤 파일의 마지막 수정 시간을 구하는 방법은 여러 가지가 있겠지만 그 중에서 생각해 볼 수 있는 것은 GetFileTime()을 이용하는 것과 GetFileAttributesEx()을 이용하는 방법이 있을 것입니다.

2 GetFileTime() 이용 #

2.1 Signature #


BOOL GetFileTime(
HANDLE hFile, // handle to file
LPFILETIME lpCreationTime, // creation time
LPFILETIME lpLastAccessTime, // last access time
LPFILETIME lpLastWriteTime // last write time
);

  • hFile: GENERIC_READ로 열은 파일 핸들이다.
  • lpCreationTime:파일의 생성 시간이다.
  • lpLastAccessTime:파일의 마지막 접근 시간이다.
  • lpLastWriteTime:파일의 마지막 수정 시간이다.

2.2 Discription #

파일의 생성, 접근, 마지막 수정 시간을 구할 수 있고, 64bit로 January 1, 1601 (UTC)로 부터의
시간을 100 nanosecond (FILETIME)로 구할 수 있습니다. 하지만 이 함수를 사용하기 위해서는 파일을
GENERIC_READ 모드로 열어야 합니다.

그래서 FindFirstChangeNotification() 함수를 함께 이용해서 파일의 변경을 확인할 때 access violation이 발생할 수 있고 이 경우 아래에서 설명할 GetFileAttributesEx()을 이용하는 것이 유리합니다.

GetFileTime으로 얻는 시간의 자료 구조인 FILETIME의 경우는 위에서 언급한 것 처럼 100 nano second까지 표현할 수 있게 다음과 같은 struct 이다.


typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;
Members
dwLowDateTime
Specifies the low-order 32 bits of the file time.
dwHighDateTime
Specifies the high-order 32 bits of the file time.

GetFileTime()을 이용해서 얻은 FILETIME은 FileTimeToLocalFileTime()과 FileTimeToSystemTime()을 이용해서 System time으로 변경할 수 있다.


BOOL FileTimeToLocalFileTime(
CONST FILETIME *lpFileTime, // UTC file time to convert
LPFILETIME lpLocalFileTime // converted file time
);
BOOL FileTimeToSystemTime(
CONST FILETIME *lpFileTime, // file time to convert
LPSYSTEMTIME lpSystemTime // receives system time
);

두 FILEITEM간 비교를 위해서 CompareFileTime()을 이용할 수도 있다.


LONG CompareFileTime(
CONST FILETIME *lpFileTime1, // first file time
CONST FILETIME *lpFileTime2 // second file time
);

2.3 Example #

아래는 “C:\\test.log” 라는 파일의 마지막 수정 시간 (last-write time)을 얻는 예제 코드입니다.


#include "stdio.h"
#include <iostream>
#include "windows.h"
/** @brief get the last-write time of the given file */
BOOL GetLastWriteTime(HANDLE hFile, LPSTR lpszString)
{
FILETIME ftCreate, ftAccess, ftWrite, ftLocal;
SYSTEMTIME stCreate;
// Retrieve the file times for the file.
if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))
return FALSE;
// Convert the last-write time to local time.
if (!FileTimeToLocalFileTime(&ftWrite, &ftLocal))
return FALSE;
// Convert the local file time from UTC to system time.
FileTimeToSystemTime(&ftLocal, &stCreate);
// Build a string showing the date and time.
wsprintf(lpszString, "%02d/%02d/%d %02d:%02d",
stCreate.wDay, stCreate.wMonth, stCreate.wYear,
stCreate.wHour, stCreate.wMinute);
return TRUE;
}
void main()
{
HANDLE hFile;
// open C:\\test.log file with GENERIC_READ
hFile = CreateFile("C:\\test.log", // open MYFILE.TXT
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // no security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return;
}
char buff[255];
memset(buff, 0x00, 255);
GetLastWriteTime(hFile, buff);
std::cout<<"file last-write time: "<<buff<<std::endl;
}

3 GetFileAttributesEx() 이용 #

3.1 Signature #


BOOL GetFileAttributesEx(
LPCTSTR lpFileName, // file or directory name
GET_FILEEX_INFO_LEVELS fInfoLevelId, // attribute class
LPVOID lpFileInformation // attribute information
);

  • lpFileName:파일 또는 디렉토리의 경로
  • fInfoLevelId:속성 정보를 담을 클래스를 지정하는 것으로 WIN32_FILE_ATTRIBUTE_DATA strcut에 정보를 담기 위해서 GetFileExInfoStandard로 지정한다.
  • lpFileInformation:파일에 대한 정보를 담을 output parameter이다. 두 번째 parameter에서 지정한 WIN32_FILE_ATTRIBUTE_DATA 구조체를 사용하며 아래와 같은 struct이다.

typedef struct _WIN32_FILE_ATTRIBUTE_DATA{
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
} WIN32_FILE_ATTRIBUTE_DATA, *LPWIN32_FILE_ATTRIBUTE_DATA;

3.2 Discription #

GetFileAttributesEx()는 파일에 관한 여러 시간 뿐만 아니라 GetFileAttributes()로 얻을 수 있는 파일의 여러 가지 속성 정보도 얻을 수 있다.
파일을 열지 않아도 아래 예제와 같이 파일 속성과 여러 시간을 구할 수 있다.

3.3 Example #

위에서 GetFileTime()의 예제를 GetFileAttributesEx()로 얻는 예제이다.


/** @brief get the last-write time of the given file */
BOOL GetLastWriteTimeByPath(const char* filePath, LPSTR lpszString)
{
if( filePath == NULL)
return FALSE;
FILETIME ftLocal;
SYSTEMTIME stCreate;
// get the file attributes
_WIN32_FILE_ATTRIBUTE_DATA fileAttData;
GetFileAttributesEx(filePath,GetFileExInfoStandard,(void*)&fileAttData);
// Convert the last-write time to local time.
if (!FileTimeToLocalFileTime(&fileAttData.ftLastWriteTime, &ftLocal))
return FALSE;
// Convert the local file time from UTC to system time.
FileTimeToSystemTime(&ftLocal, &stCreate);
// Build a string showing the date and time.
wsprintf(lpszString, "%02d/%02d/%d %02d:%02d",
stCreate.wDay, stCreate.wMonth, stCreate.wYear,
stCreate.wHour, stCreate.wMinute);
return TRUE;
}
void main()
{
char buff[255];
memset(buff, 0x00, 255);
GetLastWriteTimeByPath("C:\\test.log", buff);
std::cout<<"file last-write time: "<<buff<<std::endl;
}

Older Entries