FormatMessageW 関数 (winbase.h)
メッセージ文字列を書式設定します。 この関数には、入力としてメッセージ定義が必要です。 メッセージ定義は、関数に渡されたバッファーから取得できます。 これは、既に読み込まれているモジュールのメッセージ テーブル リソースから取得できます。 または、呼び出し元は、システムのメッセージ テーブル リソースでメッセージ定義を検索するように関数に依頼できます。 この関数は、メッセージ識別子と言語識別子に基づいて、メッセージ テーブル リソース内のメッセージ定義を検索します。 この関数は、書式設定されたメッセージ テキストを出力バッファーにコピーし、要求された場合は埋め込み挿入シーケンスを処理します。
構文
DWORD FormatMessageW(
[in] DWORD dwFlags,
[in, optional] LPCVOID lpSource,
[in] DWORD dwMessageId,
[in] DWORD dwLanguageId,
[out] LPWSTR lpBuffer,
[in] DWORD nSize,
[in, optional] va_list *Arguments
);
パラメーター
[in] dwFlags
書式設定オプションと、lpSource パラメーターを解釈する方法。 dwFlags の下位バイトは、関数が出力バッファー内の改行を処理する方法を指定します。 下位バイトでは、書式設定された出力行の最大幅を指定することもできます。
このパラメーターには、次の値のうち 1 つ以上を指定できます。
価値 | 意味 |
---|---|
|
この関数は、書式設定されたメッセージを保持するのに十分な大きさのバッファーを割り当て、lpBufferで指定されたアドレス (LPTSTR)&lpBuffer ) にキャストする必要があります。
nSize パラメーターは、出力メッセージ バッファーに割り当てる TCHAR の最小数を指定します。 呼び出し元は、LocalFree 関数を使用して、不要になったときにバッファーを解放する必要があります。
書式設定されたメッセージの長さが 128,000 バイトを超える場合、 以前のバージョンの Windows では、この値は Windows ストア アプリのコンパイル時に使用できませんでした。 Windows 10 の時点で、この値を使用できます。 Windows Server 2003 および Windows XP: 書式設定されたメッセージの長さが 128,000 バイトを超える場合、FormatMessage は、ERROR_MORE_DATAのエラーで自動的に失敗しません。 |
|
引数 パラメーターは va_list 構造体ではありませんが、引数を表す値の配列へのポインターです。
このフラグは、64 ビット整数値では使用できません。 64 ビット整数を使用している場合は、va_list 構造体を使用する必要があります。 |
|
lpSource パラメーターは、検索するメッセージ テーブル リソースを含むモジュール ハンドルです。 この モジュールにメッセージ テーブル リソースがない場合、関数は ERROR_RESOURCE_TYPE_NOT_FOUNDで失敗します。 |
|
lpSource パラメーターは、メッセージ定義を含む null で終わる文字列へのポインターです。 メッセージ定義には、メッセージ テーブル リソース内のメッセージ テキストと同様に、挿入シーケンスを含める場合があります。 このフラグは、FORMAT_MESSAGE_FROM_HMODULE または FORMAT_MESSAGE_FROM_SYSTEMで使用できません。 |
|
この関数は、システム メッセージ テーブル リソースで要求されたメッセージを検索する必要があります。 このフラグを このフラグが指定されている場合、アプリケーションは GetLastError 関数の結果を渡して、システム定義エラーのメッセージ テキストを取得できます。 |
|
%1 などの挿入シーケンスは無視され、変更されずに出力バッファーに渡されます。 このフラグは、後で書式設定するためにメッセージをフェッチする場合に便利です。 このフラグが設定されている場合、引数 パラメーターは無視されます。 |
dwFlags の下位バイトは、書式設定された出力行の最大幅を指定できます。 下位バイトの使用可能な値を次に示します。
下位バイトが FORMAT_MESSAGE_MAX_WIDTH_MASK以外の 0 以外の値の場合は、出力行の最大文字数を指定します。 この関数は、メッセージ定義テキスト内の通常の改行を無視します。 この関数は、改行の間で空白で区切られた文字列を分割することはありません。 この関数は、メッセージ定義テキスト内のハードコーディングされた改行を出力バッファーに格納します。 ハードコーディングされた改行は、%n エスケープ シーケンスでコード化されます。
[in, optional] lpSource
メッセージ定義の場所。 このパラメーターの型は、dwFlags パラメーターの設定によって異なります。
dwFlags 設定の |
意味 |
---|---|
|
検索するメッセージ テーブルを含むモジュールへのハンドル。 |
|
書式設定されていないメッセージ テキストで構成される文字列へのポインター。 挿入がスキャンされ、それに応じて書式設定されます。 |
dwFlagsでこれらのフラグ
[in] dwMessageId
要求されたメッセージのメッセージ識別子。 dwFlags
[in] dwLanguageId
要求されたメッセージの 言語識別子。 dwFlags
このパラメーターに特定の LANGID を渡すと、FormatMessage はその LANGID のみのメッセージを返します。 LANGIDのメッセージが見つからない場合は、Last-Error を ERROR_RESOURCE_LANG_NOT_FOUNDに設定します。 0 を渡した場合、FormatMessage は、次の順序で LANGIDs のメッセージを検索します。
- 言語に依存しない
- スレッド のロケール値に基づく LANGID
- ユーザーの既定 ロケール値に基づく LANGID
- システムの既定 ロケール値に基づく LANGID
- 英語 (米国)
[out] lpBuffer
書式設定されたメッセージを指定する null で終わる文字列を受け取るバッファーへのポインター。 dwFlags
このバッファーは 64K バイトを超えることはできません。
[in] nSize
FORMAT_MESSAGE_ALLOCATE_BUFFER フラグが設定されていない場合、このパラメーターは出力バッファーのサイズ TCHARで指定します。
出力バッファーは 64K バイトを超えることはできません。
[in, optional] Arguments
書式設定されたメッセージの挿入値として使用される値の配列。 書式指定文字列の %1 は、配列の 引数の最初の値 示します。%2 は 2 番目の引数を示します。などなど。
各値の解釈は、メッセージ定義の挿入に関連付けられている書式設定情報によって異なります。 既定値は、各値を null で終わる文字列へのポインターとして扱うことです。
既定では、Arguments パラメーターは va_list*型です。これは、可変数の引数を記述するための言語および実装固有のデータ型です。 va_list 引数の状態は、関数から戻ると未定義になります。 va_list をもう一度使用するには、va_end を使用して変数引数リスト ポインターを破棄し、va_startで再初期化します。
va_list*型のポインターがない場合は、FORMAT_MESSAGE_ARGUMENT_ARRAY フラグを指定し、DWORD_PTR 値の配列へのポインターを渡します。これらの値は、挿入値として書式設定されたメッセージに入力されます。 各挿入には、配列内に対応する要素が必要です。
戻り値
関数が成功した場合、戻り値は出力バッファーに格納
関数が失敗した場合、戻り値は 0 です。 拡張エラー情報を取得するには、GetLastError
備考
メッセージ テキスト内では、メッセージを動的に書式設定するために、いくつかのエスケープ シーケンスがサポートされています。 これらのエスケープ シーケンスとその意味を次の表に示します。 すべてのエスケープ シーケンスはパーセント文字 (%) で始まります。
エスケープ シーケンス | 意味 |
---|---|
%0 | メッセージ テキスト行を末尾の改行文字なしで終了します。 このエスケープ シーケンスを使用すると、長い行を作成したり、末尾の改行文字なしでメッセージ自体を終了したりできます。 プロンプト メッセージに便利です。 |
% n!書式指定文字列! |
挿入シーケンスを識別します。
n の値は、1 から 99 の範囲にすることができます。 書式指定文字列 (感嘆符で囲む必要があります) は省略可能で、既定値は !s! 指定されていない場合は 。 詳細については、「書式指定フィールド」を参照してください。
書式指定文字列には、文字列の幅と精度の指定子、および整数の幅指定子を含めることができます。 アスタリスク () を使用して、幅と精度を指定します。たとえば、!を %1します。.*s! または !*u! を %1します。 幅指定子と有効桁数指定子を使用しない場合、挿入番号は入力引数に直接対応します。 たとえば、ソース文字列が "%1 %2 %1" で、入力引数が "Bill" と "Bob" の場合、書式設定された出力文字列は "Bill Bob Bill" になります。 ただし、幅と精度指定子を使用する場合、挿入番号は入力引数に直接対応しません。 たとえば、前の例の挿入番号が "%1!*.*s! に変わる可能性があります。 !*s!" を %4 %5します。 挿入番号は、引数配列 (FORMAT_MESSAGE_ARGUMENT_ARRAY) を使用するか、va_listを使用するかによって異なります。 引数配列の場合、前の書式指定文字列にアスタリスクが 1 つ含まれていて、2 つのアスタリスクが指定されている場合は n+ 3 前の例のように "Bill" を繰り返す場合は、引数に "Bill" を 2 回含める必要があります。 たとえば、ソース文字列が "%1!*.*s! の場合です。 !*s!" %4 %5、引数には、4、2、Bill、Bob、6、Bill (FORMAT_MESSAGE_ARGUMENT_ARRAY フラグを使用している場合) を指定できます。 書式設定された文字列は "Bi Bob Bill" になります。 ソース文字列に幅指定子と有効桁数指定子が含まれている場合に挿入番号を繰り返しても、意図した結果が得られない場合があります。 %5 を %1に置き換えた場合、関数はアドレス 6 で文字列を出力しようとします (アクセス違反が発生する可能性があります)。 浮動小数点書式指定子 (e、E、f、g) はサポートされていません。 回避策は、StringCchPrintf 関数を使用して浮動小数点数を一時バッファーに書式設定し、そのバッファーを挿入文字列として使用することです。 I64 プレフィックスを使用する挿入は、2 つの 32 ビット引数として扱われます。 これらは、後続の引数を使用する前に使用する必要があります。 このプレフィックスの代わりに StringCchPrintf |
パーセント文字の後に続くその他の非デジタル文字は、パーセント文字なしで出力メッセージで書式設定されます。 いくつかの例を次に示します。
文字列の書式設定 | 結果の出力 |
---|---|
%% | 1 つのパーセント記号。 |
% スペース | 1 つのスペース。 この書式指定文字列を使用して、メッセージ テキスト行の末尾のスペースの数を適切に指定できます。 |
%. | 1 つの期間。 この書式指定文字列を使用すると、メッセージ テキスト定義を終了せずに、行の先頭に 1 つのピリオドを含めることができます。 |
%! | 単一の感嘆符。 この書式指定文字列を使用すると、挿入の直後に感嘆符を含めることができます。書式指定文字列の先頭と間違える必要はありません。 |
%n | 書式指定文字列が行の末尾に出現する場合のハード改行。 この書式指定文字列は、FormatMessage が通常の改行を提供して、メッセージが特定の幅に収まるようにする場合に便利です。 |
%r | 末尾の改行文字のないハード キャリッジ リターン。 |
%t | 1 つのタブ。 |
セキュリティに関する備考
この関数が FORMAT_MESSAGE_IGNORE_INSERTSなしで呼び出された場合、引数 パラメーターには、メッセージ文字列内のすべての挿入シーケンスを満たすのに十分なパラメーターが含まれている必要があり、正しい型である必要があります。 したがって、挿入が有効になっている信頼されていないメッセージ文字列または不明なメッセージ文字列は、引数 が提供するよりも多くの挿入シーケンスを含む可能性があるため、または正しくない型である可能性があるため、使用しないでください。 特に、API から返された任意のシステム エラー コードを取得し、FORMAT_MESSAGE_IGNORE_INSERTSなしで FORMAT_MESSAGE_FROM_SYSTEM を使用するのは安全ではありません。例
#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;
}
手記
winbase.h ヘッダーは、Unicode プリプロセッサ定数の定義に基づいて、この関数の ANSI または Unicode バージョンを自動的に選択するエイリアスとして FormatMessage を定義します。 エンコードに依存しないエイリアスをエンコードに依存しないコードと組み合わせて使用すると、コンパイルエラーやランタイム エラーが発生する不一致が発生する可能性があります。 詳細については、「関数プロトタイプの 規則」を参照してください。
必要条件
要件 | 価値 |
---|---|
サポートされる最小クライアント | Windows XP [デスクトップ アプリ |UWP アプリ] |
サポートされる最小サーバー | Windows Server 2003 [デスクトップ アプリ |UWP アプリ] |
ターゲット プラットフォーム の |
ウィンドウズ |
ヘッダー | winbase.h (Windows.h を含む) |
ライブラリ | Kernel32.lib |
DLL | Kernel32.dll |
関連項目
メッセージ テーブル