Funzione FormatMessage (winbase.h)

Formatta una stringa di messaggio. La funzione richiede una definizione di messaggio come input. La definizione del messaggio può derivare da un buffer passato alla funzione. Può venire da una risorsa di tabella dei messaggi in un modulo già caricato. Oppure il chiamante può chiedere alla funzione di cercare le risorse della tabella dei messaggi del sistema per la definizione del messaggio. La funzione trova la definizione del messaggio in una risorsa tabella messaggi in base a un identificatore di messaggio e a un identificatore di lingua. La funzione copia il testo del messaggio formattato in un buffer di output, elaborando le sequenze di inserimento incorporate se richiesto.

Sintassi

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

Parametri

[in] dwFlags

Opzioni di formattazione e come interpretare il parametro lpSource . Il byte a basso ordine di dwFlags specifica come la funzione gestisce le interruzioni di riga nel buffer di output. Il byte a basso ordine può anche specificare la larghezza massima di una riga di output formattata.

Questo parametro può essere uno o più dei valori seguenti.

Valore Significato
FORMAT_MESSAGE_ALLOCATE_BUFFER
0x00000100
La funzione alloca un buffer abbastanza grande per contenere il messaggio formattato e inserisce un puntatore al buffer allocato all'indirizzo specificato da lpBuffer. Il parametro lpBuffer è un puntatore a un LPTSTR; è necessario eseguire il cast del puntatore a un LPTSTR ,ad esempio (LPTSTR)&lpBuffer. Il parametro nSize specifica il numero minimo di TCHAR da allocare per un buffer di messaggi di output. Il chiamante deve usare la funzione LocalFree per liberare il buffer quando non è più necessario.

Se la lunghezza del messaggio formattato supera i 128K byte, FormatMessage avrà esito negativo e una chiamata successiva a GetLastError restituirà ERROR_MORE_DATA.

Nelle versioni precedenti di Windows questo valore non è stato disponibile per l'uso durante la compilazione di app di Windows Store. A partire da Windows 10 questo valore può essere usato.

Windows Server 2003 e Windows XP:

Se la lunghezza del messaggio formattato supera i 128K byte, FormatMessage non avrà esito negativo automaticamente con un errore di ERROR_MORE_DATA.

FORMAT_MESSAGE_ARGUMENT_ARRAY
0x00002000
Il parametro Arguments non è una struttura va_list , ma è un puntatore a una matrice di valori che rappresentano gli argomenti.

Questo flag non può essere usato con valori integer a 64 bit. Se si usa un intero a 64 bit, è necessario usare la struttura va_list .

FORMAT_MESSAGE_FROM_HMODULE
0x00000800
Il parametro lpSource è un handle di modulo contenente le risorse della tabella dei messaggi da cercare. Se questo handle lpSource è NULL, verrà eseguito la ricerca del file di immagine dell'applicazione del processo corrente. Questo flag non può essere usato con FORMAT_MESSAGE_FROM_STRING.

Se il modulo non ha alcuna risorsa tabella messaggi, la funzione ha esito negativo con ERROR_RESOURCE_TYPE_NOT_FOUND.

FORMAT_MESSAGE_FROM_STRING
0x00000400
Il parametro lpSource è un puntatore a una stringa con terminazione null contenente una definizione del messaggio. La definizione del messaggio può contenere sequenze di inserimento, esattamente come il testo del messaggio in una risorsa tabella messaggi può essere. Questo flag non può essere usato con FORMAT_MESSAGE_FROM_HMODULE o FORMAT_MESSAGE_FROM_SYSTEM.
FORMAT_MESSAGE_FROM_SYSTEM
0x00001000
La funzione deve cercare le risorse della tabella dei messaggi di sistema per il messaggio richiesto. Se questo flag viene specificato con FORMAT_MESSAGE_FROM_HMODULE, la funzione cerca la tabella dei messaggi di sistema se il messaggio non viene trovato nel modulo specificato da lpSource. Questo flag non può essere usato con FORMAT_MESSAGE_FROM_STRING.

Se questo flag è specificato, un'applicazione può passare il risultato della funzione GetLastError per recuperare il testo del messaggio per un errore definito dal sistema.

FORMAT_MESSAGE_IGNORE_INSERTS
0x00000200
Le sequenze di inserimento nella definizione del messaggio, ad esempio %1, devono essere ignorate e passate al buffer di output invariato. Questo flag è utile per recuperare un messaggio per la formattazione successiva. Se questo flag è impostato, il parametro Arguments viene ignorato.
 

Il byte a basso ordine di dwFlags può specificare la larghezza massima di una linea di output formattata. Di seguito sono riportati i valori possibili del byte a basso ordine.

Valore Significato
0
Non esistono restrizioni relative alla larghezza della riga di output. La funzione archivia le interruzioni di riga presenti nel testo della definizione del messaggio nel buffer di output.
FORMAT_MESSAGE_MAX_WIDTH_MASK
0x000000FF
La funzione ignora le interruzioni di riga regolari nel testo della definizione del messaggio. La funzione archivia le interruzioni di riga hardcoded nel testo della definizione del messaggio nel buffer di output. La funzione non genera nuove interruzioni di riga.
 

Se il byte a basso ordine è un valore diverso da zero rispetto a FORMAT_MESSAGE_MAX_WIDTH_MASK, specifica il numero massimo di caratteri in una riga di output. La funzione ignora le interruzioni di riga regolari nel testo della definizione del messaggio. La funzione non divide mai una stringa delimitata da spazi vuoti in un'interruzione di riga. La funzione archivia le interruzioni di riga hardcoded nel testo della definizione del messaggio nel buffer di output. Le interruzioni di riga con codice rigido vengono codificate con la sequenza di escape %n.

[in, optional] lpSource

Posizione della definizione del messaggio. Il tipo di questo parametro dipende dalle impostazioni nel parametro dwFlags .

Dwflags Impostazione Significato
FORMAT_MESSAGE_FROM_HMODULE
0x00000800
Handle al modulo contenente la tabella dei messaggi da cercare.
FORMAT_MESSAGE_FROM_STRING
0x00000400
Puntatore a una stringa costituita da testo di messaggio non formattato. Verrà analizzata per gli inserimenti e la formattazione di conseguenza.
 

Se nessuno di questi flag è impostato in dwFlags, lpSource viene ignorato.

[in] dwMessageId

Identificatore di messaggio per il messaggio richiesto. Questo parametro viene ignorato se dwFlags include FORMAT_MESSAGE_FROM_STRING.

[in] dwLanguageId

Identificatore della lingua per il messaggio richiesto. Questo parametro viene ignorato se dwFlags include FORMAT_MESSAGE_FROM_STRING.

Se si passa un LANGID specifico in questo parametro, FormatMessage restituirà un messaggio solo per tale LANGID . Se la funzione non riesce a trovare un messaggio per tale LANGID, imposta Last-Error su ERROR_RESOURCE_LANG_NOT_FOUND. Se si passa zero, FormatMessage cerca un messaggio per LANGID nell'ordine seguente:

  1. Lingua neutrale
  2. Thread LANGID, in base al valore delle impostazioni locali del thread
  3. LangID predefinito dell'utente, in base al valore delle impostazioni locali predefinite dell'utente
  4. LangID predefinito del sistema, in base al valore delle impostazioni locali predefinite del sistema
  5. Inglese (Stati Uniti)
Se FormatMessage non individua un messaggio per uno dei LANGID precedenti, restituisce qualsiasi stringa di messaggio di lingua presente. In caso contrario, restituisce ERROR_RESOURCE_LANG_NOT_FOUND.

[out] lpBuffer

Puntatore a un buffer che riceve la stringa con terminazione Null che specifica il messaggio formattato. Se dwFlags include FORMAT_MESSAGE_ALLOCATE_BUFFER, la funzione alloca un buffer usando la funzione LocalAlloc e posiziona il puntatore al buffer in corrispondenza dell'indirizzo specificato in lpBuffer.

Questo buffer non può essere maggiore di 64 KB di byte.

[in] nSize

Se il flag FORMAT_MESSAGE_ALLOCATE_BUFFER non è impostato, questo parametro specifica le dimensioni del buffer di output, in TCHAR. Se FORMAT_MESSAGE_ALLOCATE_BUFFER è impostato, questo parametro specifica il numero minimo di TCHAR da allocare per un buffer di output.

Il buffer di output non può essere maggiore di 64.000 byte.

[in, optional] Arguments

Matrice di valori utilizzati come valori di inserimento nel messaggio formattato. %1 nella stringa di formato indica il primo valore nella matrice Arguments ; un %2 indica il secondo argomento; E così via.

L'interpretazione di ogni valore dipende dalle informazioni di formattazione associate all'inserimento nella definizione del messaggio. L'impostazione predefinita consiste nel considerare ogni valore come puntatore a una stringa con terminazione Null.

Per impostazione predefinita, il parametro Arguments è di tipo va_list*, ovvero un tipo di dati specifico del linguaggio e dell'implementazione per descrivere un numero variabile di argomenti. Lo stato dell'argomento va_list non è definito al momento della restituzione dalla funzione. Per usare di nuovo il va_list , eliminare definitivamente il puntatore all'elenco di argomenti delle variabili usando va_end e reinizializzarlo con va_start.

Se non si dispone di un puntatore di tipo va_list*, specificare il flag FORMAT_MESSAGE_ARGUMENT_ARRAY e passare un puntatore a una matrice di valori DWORD_PTR ; tali valori sono input per il messaggio formattato come valori di inserimento. Ogni inserimento deve avere un elemento corrispondente nella matrice.

Valore restituito

Se la funzione ha esito positivo, il valore restituito è il numero di TCHAR archiviati nel buffer di output, escluso il carattere Null di terminazione.

Se la funzione ha esito negativo, il valore restituito è zero. Per informazioni dettagliate sull'errore, chiamare GetLastError.

Commenti

All'interno del testo del messaggio sono supportate diverse sequenze di escape per la formattazione dinamica del messaggio. Queste sequenze di escape e i relativi significati sono illustrati nelle tabelle seguenti. Tutte le sequenze di escape iniziano con il carattere percentuale (%).

Sequenza di escape Significato
%0 Termina una riga di testo del messaggio senza un carattere di nuova riga finale. Questa sequenza di escape può essere usata per creare righe lunghe o per terminare il messaggio stesso senza un carattere di nuova riga finale. È utile per i messaggi di richiesta.
%n! stringa di formato! Identifica una sequenza di inserimento. Il valore di n può essere compreso nell'intervallo compreso tra 1 e 99. La stringa di formato (che deve essere racchiusa da punti esclamativi) è facoltativa e il valore predefinito è !s! se non specificato. Per altre informazioni, vedere Campi di specifica del formato.

La stringa di formato può includere un identificatore di larghezza e precisione per le stringhe e un identificatore di larghezza per i numeri interi. Usare un asterisco () per specificare la larghezza e la precisione. Ad esempio, %1!. *s! o %1!*u!.

Se non si usano gli identificatori di larghezza e precisione, i numeri di inserimento corrispondono direttamente agli argomenti di input. Ad esempio, se la stringa di origine è "%1 %2 %1" e gli argomenti di input sono "Bill" e "Bob", la stringa di output formattata è "Bill Bob Bill".

Tuttavia, se si usa un identificatore di larghezza e precisione, i numeri di inserimento non corrispondono direttamente agli argomenti di input. Ad esempio, i numeri di inserimento per l'esempio precedente potrebbero essere modificati in "%1!*.*s! %4 %5!*s!".

I numeri di inserimento dipendono dal fatto che si usi una matrice di argomenti (FORMAT_MESSAGE_ARGUMENT_ARRAY) o una va_list. Per una matrice di argomenti, il numero di inserimento successivo è n+2 se la stringa di formato precedente contiene un asterisco e è n+3 se sono stati specificati due asterischi. Per un va_list, il numero di inserimento successivo è n+1 se la stringa di formato precedente contiene un asterisco e è n+2 se sono stati specificati due asterischi.

Se si vuole ripetere "Bill", come nell'esempio precedente, gli argomenti devono includere "Bill" due volte. Ad esempio, se la stringa di origine è "%1!*.*s! %4 %5!*s!", gli argomenti potrebbero essere, 4, 2, Bill, Bob, 6, Bill (se si usa il flag di FORMAT_MESSAGE_ARGUMENT_ARRAY ). La stringa formattata sarà quindi " Bi Bob Bill".

La ripetizione dei numeri di inserimento quando la stringa di origine contiene identificatori di larghezza e precisione potrebbe non restituire i risultati previsti. Se %5 è stato sostituito con %1, la funzione tenterà di stampare una stringa all'indirizzo 6 (probabilmente si verifica una violazione di accesso).

Gli identificatori di formato a virgola mobile, ad esempio E, f e g, non sono supportati. La soluzione alternativa consiste nell'usare la funzione StringCchPrintf per formattare il numero a virgola mobile in un buffer temporaneo, quindi usare tale buffer come stringa di inserimento.

Gli inserimenti che usano il prefisso I64 vengono considerati come due argomenti a 32 bit. Devono essere utilizzati prima dell'utilizzo degli argomenti successivi. Si noti che potrebbe essere più semplice usare StringCchPrintf anziché questo prefisso.

 

Qualsiasi altro carattere non indipendente dopo un carattere percentuale viene formattato nel messaggio di output senza il carattere percentuale. Di seguito sono riportati alcuni esempi.

Stringa di formato Output risultante
%% Un singolo segno di percentuale.
%B Uno spazio singolo. Questa stringa di formato può essere usata per garantire il numero appropriato di spazi finali in una riga di testo del messaggio.
%. Un singolo punto. Questa stringa di formato può essere utilizzata per includere un singolo punto all'inizio di una riga senza terminare la definizione del testo del messaggio.
%! Un singolo punto esclamativo. Questa stringa di formato può essere utilizzata per includere un punto esclamativo immediatamente dopo un inserimento senza che venga scambiato per l'inizio di una stringa di formato.
%n Interruzione di riga rigida quando la stringa di formato si verifica alla fine di una riga. Questa stringa di formato è utile quando FormatMessage fornisce interruzioni di riga regolari in modo che il messaggio si adatti a una certa larghezza.
%r Ritorno a capo rigido senza un carattere di nuova riga finale.
%t Una singola scheda.
 

Osservazioni sulla sicurezza

Se questa funzione viene chiamata senza FORMAT_MESSAGE_IGNORE_INSERTS, il parametro Arguments deve contenere parametri sufficienti per soddisfare tutte le sequenze di inserimento nella stringa del messaggio e devono essere del tipo corretto. Pertanto, non usare stringhe di messaggio non attendibili o sconosciute con inserimenti abilitati perché possono contenere più sequenze di inserimento rispetto a Arguments fornisce o quelle che potrebbero essere di tipo errato. In particolare, non è sicuro accettare un codice di errore di sistema arbitrario restituito da un'API e usare FORMAT_MESSAGE_FROM_SYSTEM senza FORMAT_MESSAGE_IGNORE_INSERTS.

Esempio

La funzione FormatMessage può essere usata per ottenere stringhe di messaggio di errore per i codici di errore di sistema restituiti da GetLastError. Per un esempio, vedere Recupero del codice Last-Error.

Nell'esempio seguente viene illustrato come usare una matrice di argomenti e gli identificatori di larghezza e precisione.
#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);
}


Nell'esempio seguente viene illustrato come implementare l'esempio precedente usando 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;
}

Requisiti

Requisito Valore
Client minimo supportato Windows XP [app desktop | App UWP]
Server minimo supportato Windows Server 2003 [app desktop | App UWP]
Piattaforma di destinazione Windows
Intestazione winbase.h (include Windows.h)
Libreria Kernel32.lib
DLL Kernel32.dll

Vedere anche

Funzioni di gestione degli errori

Compilatore di messaggi

Tabelle dei messaggi