なべひろBlog

プログラミングをメインに仕事に関するアレコレを発信しています。

C# 小技集

検索すれば出てきますが探すのも面倒な時の自分用備忘録な記事です。
全てMVVMなWPFを用いて自分で動作確認をやった内容です。
もくじ
例外が発生した場所を特定する
例外をキャッチした場所で
catch (Exception exc)
{
    foreach (var frame in new StackTrace(exc, true).GetFrames())
    {
        await using Log l = new(@"\Log.txt", $"例外発生 ファイル:{frame.GetFileName()} メソッド:{frame.GetMethod()} 行番号:{frame.GetFileLineNumber()} 内容:{exc.Message}");
    }
}
StackTraceのGetFramesはスタック トレース内のすべてのスタック フレームのコピーを返します。
それをforeachで回して以下の情報を取り出します。
  1. GetFileName:実行しているファイル名
  2. GetMethod:呼び出し先メソッド(非同期メソッドなどではMoveNextを取得する)
  3. GetFileLineNumber:例外が発生した行
上記例では私が以前記事にしたログ出力プログラムでテキストフィアルにログを書き込みます。
とりあえずは例外が発生したファイルと場所が分かれば不具合は追いかけやすいと思います。
マウスカーソルの状態を変える
ちょっと前に指摘されたのですがデータベースアクセス時、時間がかかると終わったタイミングがわかりにくいとの事でした。(確かに!)
そして検索すると幾つかの手法が出てくるのですが、私がやってみて問題ない手法です。
// 待機 (または砂時計) Cursor を指定します
Mouse.OverrideCursor = Cursors.Wait;
重い処理
// マウスカーソルを戻す
Mouse.OverrideCursor = null;
WPFのViewModelから実行してみましたがOKです。
シャットダウンを検出
コンストラクタで
SystemEvents.SessionEnding += sessionEnding;
ユーザーがシステムからログオフしようとした場合、またはシステムをシャットダウンしようとした場合に発生するイベントにメソッドを追加。
private void sessionEnding(object sender, SessionEndingEventArgs e)
{
    if (e.Reason == SessionEndReasons.Logoff)
    {
        MessageBox.Show("ログオフ検出");
    }
    else if (e.Reason == SessionEndReasons.SystemShutdown)
    {
        MessageBox.Show("シャットダウン検出");
    }
}
追加したメソッドの引数SessionEndingEventArgsのReasonがSessionEndReasons列挙型のどれかで判断できます。
SessionEndReasons列挙型はLogoffとSystemShutdownのみでありLogoffは数値だと1、SystemShutdownは2になります。
Encoding.GetEncodingで例外が出る時
コンストラクタなどに1行追加。
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);