Windowsのシステムエラーコードからエラーメッセージを取得する方法
GetLastError()
関数から返されるシステムエラーコードに対応するエラーメッセージ文字列を取得するために、SystemMessageクラスを書きました。
定番の処理なので車輪の再発明なのは分かっていますが、新しい C++ で書きたいよね。string_view 大好き!
ってなわけで、このSystemMessageクラスは単純で安全なリソース管理をします。
// SystemMessage.hpp #ifndef SYSTEM_MESSAGE_HPP #define SYSTEM_MESSAGE_HPP #include <Windows.h> #include <string_view> #include <stdexcept> template <typename = void> class SystemMessageImpl { LPWSTR str = nullptr; std::size_t len = 0; public: explicit SystemMessageImpl(DWORD dwMessageId, DWORD dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)) { constexpr DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM; len = ::FormatMessageW(flags, nullptr, dwMessageId, dwLanguageId, reinterpret_cast<LPWSTR>(&str), 0, nullptr); if (!len) { throw std::runtime_error("エラーメッセージの取得に失敗しました。"); } } ~SystemMessageImpl() { ::LocalFree(str); } SystemMessageImpl(const SystemMessageImpl&) = delete; SystemMessageImpl& operator=(const SystemMessageImpl&) = delete; SystemMessageImpl(SystemMessageImpl&&) = delete; SystemMessageImpl& operator=(SystemMessageImpl&&) = delete; std::wstring_view view() const { return std::wstring_view(str, len); } }; using SystemMessage = SystemMessageImpl<>; #endif // SYSTEM_MESSAGE_HPP
クラステンプレートとして実装されているので、ヘッダーオンリーのライブラリとして使えます。
これにより、複数の翻訳単位での #include
ができますし、リンケージの問題を避けられます。たぶん。
また、エラーメッセージの取得に失敗した場合には例外を投げます。
Windowsのシステムエラーコードからエラーメッセージを取得する上でおそらく問題となるのは、訳が分からない FormatMessageW()
/ FormatMessage()
の仕様と、FORMAT_MESSAGE_ALLOCATE_BUFFER
の指定で確保されたバッファをどう管理するかだと思うのですが、その辺はクラスに閉じ込めてます。
本質となるエラーメッセージは、 view()
メンバ関数呼び出して wstring_view として使ってねって設計です。
ムーブ周りまで = delete してますが、必要であれば正しく定義してください。 ここでは不要ですし、実装するのも面倒なので、楽に安全側に倒しています。
以下の例は、SystemMessageクラスを使って、現在のスレッドの最後のエラーコードに対応するメッセージを取得して表示する例です。
システムエラーメッセージを正しく表示するために setlocale()
でロケールを日本語に設定しています。
#include <clocale> #include <iostream> #include "SystemMessage.hpp" int main() { std::setlocale(LC_CTYPE, "ja_JP.UTF-8"); try { SystemMessage message{ ::GetLastError() }; std::wcout << message.view(); } catch (const std::runtime_error& e) { std::wcerr << L"エラーメッセージの取得に失敗: " << e.what() << std::endl; } }
実行結果は以下の通り。GetLastError()
が返す値によってメッセージが変わります。
この操作を正しく終了しました。
連載「技術的負債とダンスを」の目次
面白かった記事・連載を見つけたのですが、目次が見当たらず不便だったので目次を作りました。
連載「技術的負債とダンスを」の目次
- 新連載開始 (1)〜技術的負債とダンスを. 製品づくりの大きなリスクの1つは、顧客に売れないユーザに使われない製品をつくって…
- 再考:レガシーとはなんぞや?〜技術的負債とダンスを(2). ソフトウェア開発のコンテキストでレガシーと言えば、マイケル・C・フェザーズの『レ…
- レガシー改善活動のゴールのすり合わせを行おう!〜技術的負債とダンスを(3)
- リファクタリング、リアーキテクティング、ビック・リライトの選択〜技術的負債とダンスを(4)
- 連載『技術的負債とダンスを』序盤まとめ. 連載…
- 『レガシーコード改善ガイド』再入門〜 技術的負債とダンスを(5). 前回までは、『レガシーソフトウェア改善ガイド』を参考に、改善のゴールのすり合わせ…
- ユニットテスト可能なコードに変換するには「接合部」をマスターしよう〜 技術的負債とダンスを(6)
- 『レガシーコード改善ガイド』駆け足ガイド〜 技術的負債とダンスを(7)
- 継続的システムレボリューションは小さなリファクタリングの連続から始まる〜技術的負債とダンスを(8)
- 小さなリファクタリングの連続をマスターしよう〜技術的負債とダンスを(9)
- リファクタリングをいつやるか?今でしょ!〜技術的負債とダンスを(10)
- コードの不吉な臭いに気づいて早期に問題に気づいて対応しよう(1)〜技術的負債とダンスを(11)
- コードの不吉な臭いに気づいて早期に問題に気づいて対応しよう(2)〜技術的負債とダンスを(12)
- コードの不吉な臭いに気づいて早期に問題に気づいて対応しよう(3)〜技術的負債とダンスを(13)
純正カバーからサビが出てApple Storeコールセンターに電話したけどダメだった
純正カバーから出たサビのせいでiPad Airに傷がつく
お客様用に購入した純正カバーからサビが出て、そのサビのせいでカバーを取り付けていたiPad Airに傷がついてしまいました。 交換できるかApple Storeコールセンターに電話をしたのですが、カバーは交換できずiPad Airは交換できるかもという微妙な話で終わってしまいました。
電話の内容と結果について書きたいと思います。
続きを読む.NET 5.0 と VB の今後
.NET 5.0 と Visual Basic の今後
これから Visual Basic がどうなっていくのか公式の発表がありました。
以前こんな記事を書きました。
その時に VB のデスクトップ開発に力が入れられる と書きましたが、実際そうなりました。
今は .NET Core 3.1 の時代ですが、今後 .NET 5 の開発が行われていきます。 その .NET 5 では 以下の Visual Basic の開発がサポートされます。
- Class Library
- Console
- Windows Forms
- WPF
- Worker Service
- ASP.NET Core Web API
広い範囲で Visual Basic での開発がサポートされるようです。
その一方で、Visual Basic 言語そのものは今後バージョンアップされないようです。 それを「フェードアウト」とする見方もあるようですね。
個人的には非常に残念なのですが、VB を使う層がそもそも保守的で、言語を改良されることを好まない、改良されるとついていけない(ついて来ない)ような人たちが多かったようです。
C++最近の記事
C++に関するリンク
まとめる時間がないので一覧のみで
- C++メインでUE4ぷちコンに参加してみた - Qiita
- 【C++】UnitTest(C ++用Microsoft単体テストフレームワーク/vstest.Console.exe)の使い方概要 - Qiita
- 【C++】C++で作成したDLLをC++で呼ぶ(静的) - Qiita
- C#のフォームアプリからC++のモジュールを呼び出す - Qiita
- 【C++】WindowsAPIで60fpsのゲームループを実装 | のんぽぐ
- C++で文字列など込みのバイナリファイル保存 - Qiita
- C++17の新機能 落穂拾い / new features of C++17 - gleaner - Speaker Deck
- 既存のC++ネイティブプロジェクトでC#マネージドコードを使う - Qiita
- C++からC# DLL 超超超入門 - Qiita
- 【C++】任意の非型テンプレートパラメータをもたせる - Qiita
- あんちょこ:【C++】moveコンストラクタ
- C++14 の新機能 ライブラリ編 / new features of C++14 - Library - Speaker Deck
- 【C++】引数の値渡しと参照渡しを動かしながら理解【超初心者向け】 - Qiita
- 【C++】クラスの使い方 - プログラミング原人の進化論
- 【C++】インライン関数 - プログラミング原人の進化論
- C++で雪を降らす(?)CLIアプリケーション - Qiita
- midpoint - cpprefjp C++日本語リファレンス
- 4つのauto、4つのC++規格 - Qiita
- gnu c++でDLLからの例外が catch できない - Qiita
- 螺旋を描くためのC++ソースコード - 物理の駅 by onsanai
- C++でlower_boundとupper_boundを用いて区間に含まれる個数を求める - Qiita
- [C++] constexpr関数がインスタンス化されるとき - 地面を見下ろす少年の足蹴にされる私
- C++のクラス関連で調べたことメモ - ひらめの日常
- C++でzip (未完成) - Qiita
- あんちょこ:【C++】placement new
C++に関するリンク
C++に関するリンク
最近はブログの更新が滞っていました。
C++20 仕様がほぼ固まるということで、最近は C++ のブログ記事も多く出ていますね。 C++20 に限らず、C++に関する記事を紹介します。
続きを読む