Función FormatMessage (winbase.h)

Aplica formato a una cadena de mensaje. La función requiere una definición de mensaje como entrada. La definición del mensaje puede proceder de un búfer pasado a la función . Puede proceder de un recurso de tabla de mensajes en un módulo ya cargado. O bien, el autor de la llamada puede pedir a la función que busque los recursos de la tabla de mensajes del sistema para la definición del mensaje. La función busca la definición de mensaje en un recurso de tabla de mensajes en función de un identificador de mensaje y un identificador de idioma. La función copia el texto del mensaje con formato en un búfer de salida, procesando las secuencias de inserción insertadas si se solicitan.

Sintaxis

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
);

Parámetros

[in] dwFlags

Las opciones de formato y cómo interpretar el parámetro lpSource . El byte de orden bajo de dwFlags especifica cómo controla la función los saltos de línea en el búfer de salida. El byte de orden bajo también puede especificar el ancho máximo de una línea de salida con formato.

Este parámetro puede ser uno o más de los siguientes valores.

Valor Significado
FORMAT_MESSAGE_ALLOCATE_BUFFER
0x00000100
La función asigna un búfer lo suficientemente grande como para contener el mensaje con formato y coloca un puntero al búfer asignado en la dirección especificada por lpBuffer. El parámetro lpBuffer es un puntero a un LPTSTR; debe convertir el puntero a un LPTSTR (por ejemplo, (LPTSTR)&lpBuffer). El parámetro nSize especifica el número mínimo de TCHAR que se asignarán para un búfer de mensajes de salida. El autor de la llamada debe usar la función LocalFree para liberar el búfer cuando ya no sea necesario.

Si la longitud del mensaje con formato supera los 128 000 bytes, se producirá un error en FormatMessage y se devolverá una llamada posterior a GetLastErrorERROR_MORE_DATA.

En versiones anteriores de Windows, este valor no estaba disponible para su uso al compilar aplicaciones de la Tienda Windows. A partir de Windows 10 se puede usar este valor.

Windows Server 2003 y Windows XP:

Si la longitud del mensaje con formato supera los 128 000 bytes, FormatMessage no producirá automáticamente un error de ERROR_MORE_DATA.

FORMAT_MESSAGE_ARGUMENT_ARRAY
0x00002000
El parámetro Arguments no es una estructura va_list , pero es un puntero a una matriz de valores que representan los argumentos.

Esta marca no se puede usar con valores enteros de 64 bits. Si usa un entero de 64 bits, debe usar la estructura va_list .

FORMAT_MESSAGE_FROM_HMODULE
0x00000800
El parámetro lpSource es un identificador de módulo que contiene los recursos de tabla de mensajes que se van a buscar. Si este identificador lpSource es NULL, se buscará en el archivo de imagen de aplicación del proceso actual. Esta marca no se puede usar con FORMAT_MESSAGE_FROM_STRING.

Si el módulo no tiene ningún recurso de tabla de mensajes, se produce un error en la función ERROR_RESOURCE_TYPE_NOT_FOUND.

FORMAT_MESSAGE_FROM_STRING
0x00000400
El parámetro lpSource es un puntero a una cadena terminada en null que contiene una definición de mensaje. La definición del mensaje puede contener secuencias de inserción, igual que el texto del mensaje en un recurso de tabla de mensajes. Esta marca no se puede usar con FORMAT_MESSAGE_FROM_HMODULE o FORMAT_MESSAGE_FROM_SYSTEM.
FORMAT_MESSAGE_FROM_SYSTEM
0x00001000
La función debe buscar los recursos de tabla de mensajes del sistema para el mensaje solicitado. Si se especifica esta marca con FORMAT_MESSAGE_FROM_HMODULE, la función busca en la tabla de mensajes del sistema si el mensaje no se encuentra en el módulo especificado por lpSource. Esta marca no se puede usar con FORMAT_MESSAGE_FROM_STRING.

Si se especifica esta marca, una aplicación puede pasar el resultado de la función GetLastError para recuperar el texto del mensaje para un error definido por el sistema.

FORMAT_MESSAGE_IGNORE_INSERTS
0x00000200
Las secuencias de inserción en la definición de mensaje, como %1, se omitirán y pasarán al búfer de salida sin cambios. Esta marca es útil para capturar un mensaje para el formato posterior. Si se establece esta marca, se omite el parámetro Arguments .
 

El byte de orden bajo de dwFlags puede especificar el ancho máximo de una línea de salida con formato. A continuación se muestran los valores posibles del byte de orden bajo.

Valor Significado
0
No hay restricciones de ancho de línea de salida. La función almacena saltos de línea que se encuentran en el texto de definición de mensaje en el búfer de salida.
FORMAT_MESSAGE_MAX_WIDTH_MASK
0x000000FF
La función omite los saltos de línea normales en el texto de la definición del mensaje. La función almacena saltos de línea codificados de forma rígida en el texto de definición de mensaje en el búfer de salida. La función no genera saltos de línea nuevos.
 

Si el byte de orden bajo es un valor distinto de FORMAT_MESSAGE_MAX_WIDTH_MASK distinto de FORMAT_MESSAGE_MAX_WIDTH_MASK, especifica el número máximo de caracteres en una línea de salida. La función omite los saltos de línea normales en el texto de la definición del mensaje. La función nunca divide una cadena delimitada por espacios en blanco en un salto de línea. La función almacena saltos de línea codificados de forma rígida en el texto de definición de mensaje en el búfer de salida. Los saltos de línea codificados de forma rígida se codifican con la secuencia de escape %n.

[in, optional] lpSource

Ubicación de la definición del mensaje. El tipo de este parámetro depende de la configuración del parámetro dwFlags .

Dwflags Ajuste Significado
FORMAT_MESSAGE_FROM_HMODULE
0x00000800
Identificador del módulo que contiene la tabla de mensajes que se va a buscar.
FORMAT_MESSAGE_FROM_STRING
0x00000400
Puntero a una cadena que consta de texto de mensaje sin formato. Se examinarán las inserciones y se le aplicara formato en consecuencia.
 

Si ninguna de estas marcas se establece en dwFlags, lpSource se omite.

[in] dwMessageId

Identificador del mensaje solicitado. Este parámetro se omite si dwFlags incluye FORMAT_MESSAGE_FROM_STRING.

[in] dwLanguageId

Identificador de idioma del mensaje solicitado. Este parámetro se omite si dwFlags incluye FORMAT_MESSAGE_FROM_STRING.

Si pasa un LANGID específico en este parámetro, FormatMessage devolverá un mensaje solo para ese LANGID . Si la función no encuentra un mensaje para ese LANGID, establece Last-Error en ERROR_RESOURCE_LANG_NOT_FOUND. Si pasa cero, FormatMessage busca un mensaje para los LANGID en el orden siguiente:

  1. Idioma neutro
  2. LANGID del subproceso, en función del valor de configuración regional del subproceso
  3. LANGID predeterminado del usuario, en función del valor de configuración regional predeterminado del usuario
  4. LANGID predeterminado del sistema, en función del valor de configuración regional predeterminado del sistema
  5. English (Estados Unidos)
Si FormatMessage no encuentra un mensaje para ninguno de los LANGID anteriores, devuelve cualquier cadena de mensaje de idioma que esté presente. Si se produce un error, devuelve ERROR_RESOURCE_LANG_NOT_FOUND.

[out] lpBuffer

Puntero a un búfer que recibe la cadena terminada en null que especifica el mensaje con formato. Si dwFlags incluye FORMAT_MESSAGE_ALLOCATE_BUFFER, la función asigna un búfer mediante la función LocalAlloc y coloca el puntero al búfer en la dirección especificada en lpBuffer.

Este búfer no puede tener más de 64 000 bytes.

[in] nSize

Si no se establece la marca de FORMAT_MESSAGE_ALLOCATE_BUFFER , este parámetro especifica el tamaño del búfer de salida, en TCHAR. Si se establece FORMAT_MESSAGE_ALLOCATE_BUFFER , este parámetro especifica el número mínimo de TCHAR que se van a asignar para un búfer de salida.

El búfer de salida no puede tener más de 64 000 bytes.

[in, optional] Arguments

Matriz de valores que se usan como valores de inserción en el mensaje con formato. Un %1 en la cadena de formato indica el primer valor de la matriz Arguments ; un %2 indica el segundo argumento; y así sucesivamente.

La interpretación de cada valor depende de la información de formato asociada a la inserción en la definición del mensaje. El valor predeterminado es tratar cada valor como puntero a una cadena terminada en null.

De forma predeterminada, el parámetro Arguments es de tipo va_list*, que es un tipo de datos específico del lenguaje y de la implementación para describir un número variable de argumentos. El estado del argumento va_list no está definido tras la devolución de la función. Para volver a usar el va_list , destruya el puntero de lista de argumentos de variable mediante va_end y vuelva a inicializarlo con va_start.

Si no tiene un puntero de tipo va_list*, especifique la marca FORMAT_MESSAGE_ARGUMENT_ARRAY y pase un puntero a una matriz de valores de DWORD_PTR ; esos valores se introducen en el mensaje con formato como valores de inserción. Cada inserción debe tener un elemento correspondiente en la matriz.

Valor devuelto

Si la función se ejecuta correctamente, el valor devuelto es el número de TCHAR almacenados en el búfer de salida, excepto el carácter nulo de terminación.

Si la función no se realiza correctamente, el valor devuelto es cero. Para obtener información de error extendida, llame a GetLastError.

Comentarios

Dentro del texto del mensaje, se admiten varias secuencias de escape para aplicar formato al mensaje de forma dinámica. Estas secuencias de escape y sus significados se muestran en las tablas siguientes. Todas las secuencias de escape comienzan con el carácter de porcentaje (%).

Secuencia de escape Significado
%0 Finaliza una línea de texto de mensaje sin un carácter de línea nuevo final. Esta secuencia de escape se puede usar para crear líneas largas o para finalizar el propio mensaje sin un carácter de línea nuevo final. Resulta útil para solicitar mensajes.
%¡n! cadena de formato! Identifica una secuencia de inserción. El valor de n puede estar en el intervalo comprendido entre 1 y 99. La cadena de formato (que debe estar rodeada por signos de exclamación) es opcional y el valor predeterminado es !s! si no se especifica. Para obtener más información, vea Format Specification Fields.

La cadena de formato puede incluir un especificador de ancho y precisión para cadenas y un especificador de ancho para enteros. Use un asterisco () para especificar el ancho y la precisión. Por ejemplo, %1!. *s! o %1!*u!.

Si no usa los especificadores de ancho y precisión, los números de inserción se corresponden directamente con los argumentos de entrada. Por ejemplo, si la cadena de origen es "%1 %2 %1" y los argumentos de entrada son "Bill" y "Bob", la cadena de salida con formato es "Bill Bob Bill".

Sin embargo, si usa un especificador de ancho y precisión, los números de inserción no se corresponden directamente con los argumentos de entrada. Por ejemplo, los números de inserción del ejemplo anterior podrían cambiar a "%1!*.*s! %4 %5!*s!".

Los números de inserción dependen de si se usa una matriz de argumentos (FORMAT_MESSAGE_ARGUMENT_ARRAY) o un va_list. Para una matriz de argumentos, el número de inserción siguiente es n+2 si la cadena de formato anterior contenía un asterisco y es n+3 si se especificaron dos asteriscos. Para un va_list, el número de inserción siguiente es n+1 si la cadena de formato anterior contenía un asterisco y es n+2 si se especificaron dos asteriscos.

Si desea repetir "Bill", como en el ejemplo anterior, los argumentos deben incluir "Bill" dos veces. Por ejemplo, si la cadena de origen es "%1!*.*s! %4 %5!*s!", los argumentos podrían ser, 4, 2, Bill, Bob, 6, Bill (si se usa la marca FORMAT_MESSAGE_ARGUMENT_ARRAY ). La cadena con formato sería " Bi Bob Bill".

Repetir números de inserción cuando la cadena de origen contiene especificadores de ancho y precisión puede no producir los resultados previstos. Si ha reemplazado %5 por %1, la función intentará imprimir una cadena en la dirección 6 (lo que probablemente provocaría una infracción de acceso).

No se admiten especificadores de formato de punto flotante (e, E, f y g). La solución consiste en usar la función StringCchPrintf para dar formato al número de punto flotante en un búfer temporal y, a continuación, usar ese búfer como cadena de inserción.

Las inserciones que usan el prefijo I64 se tratan como dos argumentos de 32 bits. Deben usarse antes de que se usen argumentos posteriores. Tenga en cuenta que puede ser más fácil usar StringCchPrintf en lugar de este prefijo.

 

Cualquier otro carácter nondigit después de un carácter de porcentaje se da formato en el mensaje de salida sin el carácter de porcentaje. A continuación se muestran algunos ejemplos.

Cadena de formato Salida resultante
%% Signo de un solo porcentaje.
%b Un solo espacio. Esta cadena de formato se puede usar para garantizar el número adecuado de espacios finales en una línea de texto de mensaje.
%. Un único período. Esta cadena de formato se puede usar para incluir un único punto al principio de una línea sin terminar la definición de texto del mensaje.
%! Un único signo de exclamación. Esta cadena de formato se puede usar para incluir un signo de exclamación inmediatamente después de una inserción sin que se equivoque al principio de una cadena de formato.
%n Salto de línea dura cuando la cadena de formato se produce al final de una línea. Esta cadena de formato es útil cuando FormatMessage proporciona saltos de línea normales para que el mensaje se ajuste a un ancho determinado.
%r Retorno de carro duro sin un carácter de nueva línea final.
%t Una sola pestaña.
 

Comentarios de seguridad

Si se llama a esta función sin FORMAT_MESSAGE_IGNORE_INSERTS, el parámetro Arguments debe contener suficientes parámetros para satisfacer todas las secuencias de inserción de la cadena de mensaje y deben ser del tipo correcto. Por lo tanto, no use cadenas de mensaje que no sean de confianza o desconocidas con inserciones habilitadas porque pueden contener más secuencias de inserción que las que proporciona Arguments o aquellas que pueden ser del tipo incorrecto. En concreto, no es seguro tomar un código de error arbitrario del sistema devuelto por una API y usar FORMAT_MESSAGE_FROM_SYSTEM sin FORMAT_MESSAGE_IGNORE_INSERTS.

Ejemplos

La función FormatMessage se puede usar para obtener cadenas de mensaje de error para los códigos de error del sistema devueltos por GetLastError. Para obtener un ejemplo, consulte Recuperación del código de Last-Error.

En el ejemplo siguiente se muestra cómo usar una matriz de argumentos y los especificadores de ancho y precisión.
#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);
}


En el ejemplo siguiente se muestra cómo implementar el ejemplo anterior mediante 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;
}

Requisitos

Requisito Value
Cliente mínimo compatible Windows XP [aplicaciones de escritorio | aplicaciones para UWP]
Servidor mínimo compatible Windows Server 2003 [aplicaciones de escritorio | aplicaciones para UWP]
Plataforma de destino Windows
Encabezado winbase.h (incluya Windows.h)
Library Kernel32.lib
Archivo DLL Kernel32.dll

Vea también

Funciones de control de errores

Compilador de mensaje

Tablas de mensajes