FormatMessage 함수(winbase.h)

메시지 문자열의 형식을 지정합니다. 함수에는 메시지 정의가 입력으로 필요합니다. 메시지 정의는 함수에 전달된 버퍼에서 올 수 있습니다. 이미 로드된 모듈의 메시지 테이블 리소스에서 올 수 있습니다. 또는 호출자는 함수에 시스템의 메시지 테이블 리소스에서 메시지 정의를 검색하도록 요청할 수 있습니다. 함수는 메시지 식별자 및 언어 식별자를 기반으로 메시지 테이블 리소스에서 메시지 정의를 찾습니다. 함수는 형식이 지정된 메시지 텍스트를 출력 버퍼에 복사하여 요청된 경우 포함된 삽입 시퀀스를 처리합니다.

구문

DWORD FormatMessage(
  [in]           DWORD   dwFlags,
  [in, optional] LPCVOID lpSource,
  [in]           DWORD   dwMessageId,
  [in]           DWORD   dwLanguageId,
  [out]          LPTSTR  lpBuffer,
  [in]           DWORD   nSize,
  [in, optional] va_list *Arguments
);

매개 변수

[in] dwFlags

서식 옵션 및 lpSource 매개 변수를 해석하는 방법입니다. dwFlags의 하위 바이트는 함수가 출력 버퍼에서 줄 바꿈을 처리하는 방법을 지정합니다. 낮은 순서의 바이트는 서식이 지정된 출력 줄의 최대 너비를 지정할 수도 있습니다.

이 매개 변수는 다음 값 중 하나 이상일 수 있습니다.

의미
FORMAT_MESSAGE_ALLOCATE_BUFFER
0x00000100
함수는 서식이 지정된 메시지를 저장할 수 있을 만큼 큰 버퍼를 할당하고 lpBuffer에서 지정한 주소에 할당된 버퍼에 대한 포인터를 배치합니다. lpBuffer 매개 변수는 LPTSTR에 대한 포인터입니다. 포인터를 LPTSTR(예(LPTSTR)&lpBuffer: )로 캐스팅해야 합니다. nSize 매개 변수는 출력 메시지 버퍼에 할당할 최소 TCHAR 수를 지정합니다. 호출자는 더 이상 필요하지 않은 경우 LocalFree 함수를 사용하여 버퍼를 해제해야 합니다.

형식이 지정된 메시지의 길이가 128K 바이트를 초과하면 FormatMessage 가 실패하고 GetLastError 에 대한 후속 호출은 ERROR_MORE_DATA 반환합니다.

이전 버전의 Windows에서는 Windows 스토어 앱을 컴파일할 때 이 값을 사용할 수 없었습니다. Windows 10 이 값을 사용할 수 있습니다.

Windows Server 2003 및 Windows XP:

서식이 지정된 메시지의 길이가 128K 바이트를 초과하는 경우 FormatMessageERROR_MORE_DATA 오류와 함께 자동으로 실패하지 않습니다.

FORMAT_MESSAGE_ARGUMENT_ARRAY
0x00002000
Arguments 매개 변수는 va_list 구조체가 아니라 인수를 나타내는 값 배열에 대한 포인터입니다.

이 플래그는 64비트 정수 값과 함께 사용할 수 없습니다. 64비트 정수 를 사용하는 경우 va_list 구조를 사용해야 합니다.

FORMAT_MESSAGE_FROM_HMODULE
0x00000800
lpSource 매개 변수는 검색할 메시지 테이블 리소스를 포함하는 모듈 핸들입니다. 이 lpSource 핸들이 NULL이면 현재 프로세스의 애플리케이션 이미지 파일이 검색됩니다. 이 플래그는 FORMAT_MESSAGE_FROM_STRING 사용할 수 없습니다.

모듈에 메시지 테이블 리소스가 없으면 ERROR_RESOURCE_TYPE_NOT_FOUND 함께 함수가 실패합니다.

FORMAT_MESSAGE_FROM_STRING
0x00000400
lpSource 매개 변수는 메시지 정의를 포함하는 null로 끝나는 문자열에 대한 포인터입니다. 메시지 정의에는 메시지 테이블 리소스의 메시지 텍스트와 마찬가지로 삽입 시퀀스가 포함될 수 있습니다. 이 플래그는 FORMAT_MESSAGE_FROM_HMODULE 또는 FORMAT_MESSAGE_FROM_SYSTEM 사용할 수 없습니다.
FORMAT_MESSAGE_FROM_SYSTEM
0x00001000
함수는 시스템 message-table 리소스에서 요청된 메시지를 검색해야 합니다. 이 플래그가 FORMAT_MESSAGE_FROM_HMODULE 지정되면 함수는 lpSource로 지정된 모듈에서 메시지를 찾을 수 없는 경우 시스템 메시지 테이블을 검색합니다. 이 플래그는 FORMAT_MESSAGE_FROM_STRING 사용할 수 없습니다.

이 플래그를 지정하면 애플리케이션이 GetLastError 함수의 결과를 전달하여 시스템 정의 오류에 대한 메시지 텍스트를 검색할 수 있습니다.

FORMAT_MESSAGE_IGNORE_INSERTS
0x00000200
%1과 같은 메시지 정의에 삽입 시퀀스를 무시하고 출력 버퍼에 변경되지 않은 상태로 전달해야 합니다. 이 플래그는 나중에 서식을 지정하기 위해 메시지를 가져오는 데 유용합니다. 이 플래그를 설정하면 Arguments 매개 변수가 무시됩니다.
 

dwFlags의 낮은 순서 바이트는 서식이 지정된 출력 줄의 최대 너비를 지정할 수 있습니다. 다음은 낮은 바이트의 가능한 값입니다.

의미
0
출력 선 너비 제한이 없습니다. 함수는 메시지 정의 텍스트에 있는 줄 바꿈을 출력 버퍼에 저장합니다.
FORMAT_MESSAGE_MAX_WIDTH_MASK
0x000000FF
함수는 메시지 정의 텍스트에서 일반 줄 바꿈을 무시합니다. 함수는 메시지 정의 텍스트에 하드 코딩된 줄 바꿈을 출력 버퍼에 저장합니다. 함수는 새 줄 바꿈을 생성하지 않습니다.
 

하위 바이트가 FORMAT_MESSAGE_MAX_WIDTH_MASK 이외의 0이 아닌 값인 경우 출력 줄의 최대 문자 수를 지정합니다. 함수는 메시지 정의 텍스트에서 일반 줄 바꿈을 무시합니다. 함수는 줄 바꿈에 공백으로 구분된 문자열을 분할하지 않습니다. 함수는 메시지 정의 텍스트에 하드 코딩된 줄 바꿈을 출력 버퍼에 저장합니다. 하드 코딩된 줄 바꿈은 %n 이스케이프 시퀀스로 코딩됩니다.

[in, optional] lpSource

메시지 정의의 위치입니다. 이 매개 변수의 형식은 dwFlags 매개 변수의 설정에 따라 달라집니다.

dwFlags 설정 의미
FORMAT_MESSAGE_FROM_HMODULE
0x00000800
검색할 메시지 테이블이 포함된 모듈에 대한 핸들입니다.
FORMAT_MESSAGE_FROM_STRING
0x00000400
서식이 지정되지 않은 메시지 텍스트로 구성된 문자열에 대한 포인터입니다. 삽입을 검사하고 그에 따라 서식을 지정합니다.
 

이러한 플래그 중 어느 것도 dwFlags에서 설정되지 않은 경우 lpSource 는 무시됩니다.

[in] dwMessageId

요청된 메시지의 메시지 식별자입니다. dwFlagsFORMAT_MESSAGE_FROM_STRING 포함된 경우 이 매개 변수는 무시됩니다.

[in] dwLanguageId

요청된 메시지의 언어 식별자 입니다. dwFlagsFORMAT_MESSAGE_FROM_STRING 포함된 경우 이 매개 변수는 무시됩니다.

이 매개 변수에서 특정 LANGID 를 전달하는 경우 FormatMessage 는 해당 LANGID 에 대한 메시지만 반환합니다. 함수가 해당 LANGID에 대한 메시지를 찾을 수 없는 경우 Last-Error ERROR_RESOURCE_LANG_NOT_FOUND 설정합니다. 0을 전달하면 FormatMessage 는 다음 순서대로 LANGID 에 대한 메시지를 찾습니다.

  1. 언어 중립
  2. 스레드의 로캘 값을 기반으로 하는 Thread LANGID
  3. 사용자의 기본 로캘 값에 따라 사용자 기본 LANGID
  4. 시스템 기본 로캘 값을 기반으로 하는 시스템 기본 LANGID
  5. 영어
FormatMessage가 이전 LANGID에 대한 메시지를 찾지 못하면 존재하는 언어 메시지 문자열을 반환합니다. 실패하면 ERROR_RESOURCE_LANG_NOT_FOUND 반환합니다.

[out] lpBuffer

형식이 지정된 메시지를 지정하는 null로 끝나는 문자열을 수신하는 버퍼에 대한 포인터입니다. dwFlagsFORMAT_MESSAGE_ALLOCATE_BUFFER 포함된 경우 함수는 LocalAlloc 함수를 사용하여 버퍼를 할당하고 lpBuffer에 지정된 주소에 버퍼에 대한 포인터를 배치합니다.

이 버퍼는 64K 바이트를 초과할 수 없습니다.

[in] nSize

FORMAT_MESSAGE_ALLOCATE_BUFFER 플래그가 설정되지 않은 경우 이 매개 변수는 TCHAR에서 출력 버퍼의 크기를 지정합니다. FORMAT_MESSAGE_ALLOCATE_BUFFER 설정된 경우 이 매개 변수는 출력 버퍼에 할당할 최소 TCHAR 수를 지정합니다.

출력 버퍼는 64K 바이트보다 클 수 없습니다.

[in, optional] Arguments

서식이 지정된 메시지의 삽입 값으로 사용되는 값의 배열입니다. 형식 문자열의 %1은 인수 배열의 첫 번째 값을 나타냅니다. %2는 두 번째 인수를 나타냅니다. 등등.

각 값의 해석은 메시지 정의의 삽입과 관련된 서식 정보에 따라 달라집니다. 기본값은 각 값을 null로 끝나는 문자열에 대한 포인터로 처리하는 것입니다.

기본적으로 Arguments 매개 변수는 변수 수의 인수를 설명하는 언어 및 구현별 데이터 형식인 va_list*형식입니다. va_list 인수의 상태는 함수에서 반환될 때 정의되지 않습니다. va_list 다시 사용하려면 va_end 사용하여 변수 인수 목록 포인터를 삭제하고 va_start 사용하여 다시 초기화합니다.

va_list*형식의 포인터가 없는 경우 FORMAT_MESSAGE_ARGUMENT_ARRAY 플래그를 지정하고 포인터를 DWORD_PTR 값 배열에 전달합니다. 이러한 값은 삽입 값으로 서식이 지정된 메시지에 입력됩니다. 각 삽입에는 배열에 해당 요소가 있어야 합니다.

반환 값

함수가 성공하면 반환 값은 종료 null 문자를 제외하고 출력 버퍼에 저장된 TCHAR 의 수입니다.

함수가 실패하면 반환 값은 0입니다. 확장 오류 정보를 가져오려면 GetLastError를 호출합니다.

설명

메시지 텍스트 내에서 메시지 서식을 동적으로 지정하기 위해 여러 이스케이프 시퀀스가 지원됩니다. 이러한 이스케이프 시퀀스와 해당 의미는 다음 표에 나와 있습니다. 모든 이스케이프 시퀀스는 백분율 문자(%)로 시작합니다.

이스케이프 시퀀스 의미
%0 후행 새 줄 문자 없이 메시지 텍스트 줄을 종료합니다. 이 이스케이프 시퀀스는 긴 줄을 작성하거나 후행 새 줄 문자 없이 메시지 자체를 종료하는 데 사용할 수 있습니다. 프롬프트 메시지에 유용합니다.
%n! 형식 문자열! 삽입 시퀀스를 식별합니다. n 값은 1에서 99까지의 범위에 있을 수 있습니다. 형식 문자열(느낌표로 묶어야 합니다)은 선택 사항이며 기본값은 !s!입니다. 지정되지 않은 경우 입니다. 자세한 내용은 사양 필드 서식을 참조하세요.

형식 문자열에는 문자열의 너비 및 전체 자릿수 지정자와 정수의 너비 지정자가 포함될 수 있습니다. 별표()를 사용하여 너비와 전체 자릿수를 지정합니다. 예를 들어 %1!입니다. *s! 또는 %1!*u!.

너비 및 전체 자릿수 지정자를 사용하지 않는 경우 삽입 숫자는 입력 인수에 직접 해당합니다. 예를 들어 원본 문자열이 "%1 %2 %1"이고 입력 인수가 "Bill" 및 "Bob"인 경우 형식이 지정된 출력 문자열은 "Bill Bob Bill"입니다.

그러나 너비 및 전체 자릿수 지정자를 사용하는 경우 삽입 숫자는 입력 인수에 직접 해당하지 않습니다. 예를 들어 이전 예제의 삽입 번호는 "%1!*.*s! %4 %5!*s!".

삽입 번호는 인수 배열(FORMAT_MESSAGE_ARGUMENT_ARRAY) 또는 va_list 사용하는지 여부에 따라 달라집니다. 인수 배열의 경우 이전 형식 문자열에 별표가 하나 있는 경우 다음 삽입 번호는 n+2 이고 두 개의 별표가 지정된 경우 n+3 입니다. va_list 경우 이전 형식 문자열에 별표가 하나 있는 경우 다음 삽입 번호는 n+1이고 두 개의 별표가 지정된 경우 n+2입니다.

이전 예제와 같이 "Bill"을 반복하려면 인수에 "Bill"이 두 번 포함되어야 합니다. 예를 들어 원본 문자열이 "%1!*.*s! %4 %5!*s!", 인수는 4, 2, Bill, Bob, 6, Bill( FORMAT_MESSAGE_ARGUMENT_ARRAY 플래그를 사용하는 경우)일 수 있습니다. 형식이 지정된 문자열은 "Bi Bob Bill"이 됩니다.

원본 문자열에 너비가 포함되고 전체 자릿수 지정자가 있는 경우 삽입 숫자를 반복하면 의도한 결과가 생성되지 않을 수 있습니다. %5를 %1로 바꾼 경우 함수는 주소 6에서 문자열을 인쇄하려고 합니다(액세스 위반이 발생할 수 있습니다).

부동 소수점 형식 지정자(예: E, f 및 g)는 지원되지 않습니다. 해결 방법은 StringCchPrintf 함수를 사용하여 부동 소수점 숫자를 임시 버퍼로 포맷한 다음 해당 버퍼를 삽입 문자열로 사용하는 것입니다.

I64 접두사를 사용하는 삽입은 두 개의 32비트 인수로 처리됩니다. 후속 인수를 사용하려면 먼저 사용해야 합니다. 이 접두사 대신 StringCchPrintf 를 사용하는 것이 더 쉬울 수 있습니다.

 

백분율 문자 뒤에 있는 다른 모든 비디지트 문자는 백분율 문자 없이 출력 메시지에 서식이 지정됩니다. 다음은 몇 가지 예입니다.

형식 문자열 결과 출력
%% 단일 백분율 기호입니다.
%B 단일 공간입니다. 이 서식 문자열을 사용하여 메시지 텍스트 줄에서 적절한 수의 후행 공백을 확인할 수 있습니다.
%. 단일 마침표입니다. 이 서식 문자열은 메시지 텍스트 정의를 종료하지 않고 줄의 시작 부분에 단일 마침표가 포함되는 데 사용할 수 있습니다.
%! 단일 느낌표입니다. 이 형식 문자열은 형식 문자열의 시작 부분으로 오인되지 않고 삽입 직후 느낌표를 포함하는 데 사용할 수 있습니다.
%n 줄의 끝에서 서식 문자열이 발생할 때의 하드 줄 바꿈입니다. 이 형식 문자열은 FormatMessage 가 일반 줄 바꿈을 제공하여 메시지가 특정 너비에 맞도록 하는 경우에 유용합니다.
%r 후행 줄다리기 문자가 없는 하드 캐리지 리턴입니다.
%t 단일 탭.
 

보안 설명

이 함수가 FORMAT_MESSAGE_IGNORE_INSERTS 없이 호출되는 경우 Arguments 매개 변수에는 메시지 문자열의 모든 삽입 시퀀스를 충족할 수 있는 충분한 매개 변수가 포함되어야 하며 올바른 형식이어야 합니다. 따라서 인수 가 제공하는 것보다 더 많은 삽입 시퀀스 또는 잘못된 형식일 수 있는 삽입 시퀀스를 포함할 수 있으므로 삽입이 활성화된 신뢰할 수 없거나 알 수 없는 메시지 문자열을 사용하지 마세요. 특히 API에서 반환된 임의의 시스템 오류 코드를 사용하고 FORMAT_MESSAGE_IGNORE_INSERTS 없이 FORMAT_MESSAGE_FROM_SYSTEM 사용하는 것은 안전하지 않습니다.

예제

FormatMessage 함수를 사용하여 GetLastError에서 반환된 시스템 오류 코드에 대한 오류 메시지 문자열을 가져올 수 있습니다. 예제는 Last-Error 코드 검색을 참조하세요.

다음 예제에서는 인수 배열과 너비 및 전체 자릿수 지정자를 사용하는 방법을 보여 줍니다.
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>

void main(void)
{
    LPWSTR pMessage = L"%1!*.*s! %4 %5!*s!";
    DWORD_PTR pArgs[] = { (DWORD_PTR)4, (DWORD_PTR)2, (DWORD_PTR)L"Bill",  // %1!*.*s! refers back to the first insertion string in pMessage
         (DWORD_PTR)L"Bob",                                                // %4 refers back to the second insertion string in pMessage
         (DWORD_PTR)6, (DWORD_PTR)L"Bill" };                               // %5!*s! refers back to the third insertion string in pMessage
    const DWORD size = 100+1;
    WCHAR buffer[size];


    if (!FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
                       pMessage, 
                       0,
                       0,
                       buffer, 
                       size, 
                       (va_list*)pArgs))
    {
        wprintf(L"Format message failed with 0x%x\n", GetLastError());
        return;
    }

    // Buffer contains "  Bi Bob   Bill".
    wprintf(L"Formatted message: %s\n", buffer);
}


다음 예제에서는 va_list 사용하여 이전 예제를 구현하는 방법을 보여줍니다.

#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>

LPWSTR GetFormattedMessage(LPWSTR pMessage, ...);

void main(void)
{
    LPWSTR pBuffer = NULL;
    LPWSTR pMessage = L"%1!*.*s! %3 %4!*s!";

    // The variable length arguments correspond directly to the format
    // strings in pMessage.
    pBuffer = GetFormattedMessage(pMessage, 4, 2, L"Bill", L"Bob", 6, L"Bill");
    if (pBuffer)
    {
        // Buffer contains "  Bi Bob   Bill".
        wprintf(L"Formatted message: %s\n", pBuffer);
        LocalFree(pBuffer);
    }
    else
    {
        wprintf(L"Format message failed with 0x%x\n", GetLastError());
    }
}

// Formats a message string using the specified message and variable
// list of arguments.
LPWSTR GetFormattedMessage(LPWSTR pMessage, ...)
{
    LPWSTR pBuffer = NULL;

    va_list args = NULL;
    va_start(args, pMessage);

    FormatMessage(FORMAT_MESSAGE_FROM_STRING |
                  FORMAT_MESSAGE_ALLOCATE_BUFFER,
                  pMessage, 
                  0,
                  0,
                  (LPWSTR)&pBuffer, 
                  0, 
                  &args);

    va_end(args);

    return pBuffer;
}

요구 사항

요구 사항
지원되는 최소 클라이언트 Windows XP [데스크톱 앱 | UWP 앱]
지원되는 최소 서버 Windows Server 2003 [데스크톱 앱 | UWP 앱]
대상 플랫폼 Windows
헤더 winbase.h(Windows.h 포함)
라이브러리 Kernel32.lib
DLL Kernel32.dll

참고 항목

오류 처리 함수

메시지 컴파일러

메시지 테이블