potisanのプログラミングメモ

プログラミング素人です。昔の自分を育ててくれたネット情報に少しでも貢献できるよう、情報を貯めていこうと思っています。Windows環境のC++やC#がメインです。

17 C++&Win32 API ファイルの多言語対応リソースの言語とファイルパスを取得する

C++とWin32 APIでファイルの多言語対応リソース(Microsoft Docsでは「language-specific resource files」)の言語名とMUIファイルパスを取得するサンプルコードです。

// 動作確認環境:C++ 17
#include <io.h>
#include <fcntl.h>

#include <array>
#include <filesystem>
#include <iostream>
#include <string>

#define STRICT
#include <Windows.h>

using namespace std;

filesystem::path get_system_directory() noexcept;

int main()
{
    const auto path = get_system_directory() / L"comctl32.dll";

    // ユニコードモードの設定
    _setmode(_fileno(stdout), _O_U16TEXT);

    // 言語名とMUIファイルパスの最大長の取得
    ULONG maxLangLen;
    ULONG maxFileMuiPath;
    ULONGLONG enumId = 0;
    if (!GetFileMUIPath(MUI_USE_SEARCH_ALL_LANGUAGES, path.c_str(),
        nullptr, &maxLangLen, nullptr, &maxFileMuiPath, &enumId))
    {
        return 0;
    }

    // バッファーの確保
    wstring lang(maxLangLen, L'\0');
    wstring fileMuiPath(maxFileMuiPath, L'\0');

    // 言語の名前とMUIファイルパスの取得
    for (;;)
    {
        ULONG langLen = maxLangLen;
        ULONG fileMuiPathLen = maxFileMuiPath;
        if (!GetFileMUIPath(MUI_USE_SEARCH_ALL_LANGUAGES, path.c_str(),
            lang.data(), &langLen, fileMuiPath.data(), &fileMuiPathLen, &enumId))
        {
            break;
        }
        wcout << lang << L"," << fileMuiPath << endl;
    }

    return 0;
}

filesystem::path get_system_directory() noexcept
{
    array<WCHAR, MAX_PATH> buffer;
    if (!GetSystemDirectoryW(buffer.data(), static_cast<DWORD>(buffer.size()))) {
        return {};
    }
    return buffer.data();
}

参考