2022年9月12日月曜日

ASP.NET MVC "Cannot perform runtime binding on a null reference"

これは初見の人にとっては厄介な問題です。

 
[RuntimeBinderException: Cannot perform runtime binding on a null reference]
   CallSite.Target(Closure , CallSite , Object ) +148
   System.Dynamic.UpdateDelegates.UpdateAndExecute1(CallSite site, T0 arg0) +664 
   ...
 
初見の人にとって厄介な理由は、修正すべき場所とは異なる場所が指摘されるからです。
 
この例については…
luckyNumber はきちんと初期化しています。
luckyNumber に問題が無い事は明らかです。
 
 
未初期化のフィールドへアクセスしていないかどうかを確認しましょう。
 
この場合は @Model へのアクセスが問題です。
@Model を一切初期化していないのにも関わらず、
@Model へアクセスしようとしています。
 

@Model については @model 宣言をしない場合 dynamic 型として解決されるようです。
dynamic 型は実行時に解決されます。
実行するまでエラーが発生しないため、見過ごしてしまう事が懸念されます。

他のソースコードから input タグ等をコピーしてきた場合に起こり得ます。
@Model は存在しないので value 属性ごと削除しても良いでしょう。


2022年6月1日水曜日

Debugging Tools for Windows の cdb.exe を使って .NET Framework 4.0 アプリのクラッシュダンプから stack trace を得る

Debugging Tools for Windows の cdb.exe を使って .NET Framework 4.0 アプリのクラッシュダンプから stack trace を得る

 

スタックトレースだけを取得したい場合、cdb.exe をワンライナーで使う手もあると思います。

 

cdb.exe は「Windows 用デバッグ ツール (WinDbg)」セットアップに含まれています。

Windows 用デバッグ ツールのダウンロード を参照して、入手してください。

 

X64 Debuggers And Tools-x64_en-us.msi を既定の設定でセットアップした場合:

"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe"

X86 Debuggers And Tools-x86_en-us.msi を既定の設定でセットアップした場合:

"C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe"


参考: CDB のコマンドライン オプション

コマンドライン 64-bit 用:

"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe" -z "C:\ProgramData\Wazato\Wazato.exe.21264.dmp" -aC:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll -lines -c "!sos.printexception -nested -lines" < nul

コマンドライン 32-bit 用 :

"C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe" -z "C:\ProgramData\Wazato\Wazato.exe.21264.dmp" -aC:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll -lines -c "!sos.printexception -nested -lines" < nul

出力:

Microsoft (R) Windows Debugger Version 10.0.22621.1 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.


Loading Dump File [C:\ProgramData\Wazato\Wazato.exe.24684.dmp]
User Mini Dump File: Only registers, stack and portions of memory are available

Symbol search path is: srv*
Executable search path is:
Windows 10 Version 19044 MP (4 procs) Free x64
Product: WinNt, suite: SingleUserTS
Edition build lab: 19041.1.amd64fre.vb_release.191206-1406
Machine Name:
Debug session time: Wed Jun  1 21:56:33.000 2022 (UTC + 9:00)
System Uptime: not available
Process Uptime: 0 days 0:00:04.000
...................................
Loading unloaded module list
.
----------------------------------------------------------------------------
The user dump currently examined is a minidump. Consequently, only a subset
of sos.dll functionality will be available. If needed, attaching to the live
process or debugging a full dump will allow access to sos.dll's full feature
set.
To create a full user dump use the command: .dump /ma <filename>
----------------------------------------------------------------------------
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(606c.4a64): CLR exception - code e0434352 (first/second chance not available)
For analysis of this file, run !analyze -v
ntdll!NtWaitForMultipleObjects+0x14:
00007ff8`85f4d894 c3              ret
0:000> cdb: Reading initial command '!sos.printexception -nested -lines'
----------------------------------------------------------------------------
The user dump currently examined is a minidump. Consequently, only a subset
of sos.dll functionality will be available. If needed, attaching to the live
process or debugging a full dump will allow access to sos.dll's full feature
set.
To create a full user dump use the command: .dump /ma <filename>
----------------------------------------------------------------------------
Exception object: 0000000002f28178
Exception type:   System.Exception
Message:          例外が発生しました。
InnerException:   Wazato.WazatoException, Use !PrintException 0000000002f28030 to see more.
StackTrace (generated):
*** WARNING: Unable to verify checksum for Wazato.exe
    SP               IP               Function
    0000000000DCCB60 00007FF807220961 Wazato!Wazato.Program.Main(System.String[])+0xd1 [H:\Proj\Wazato\Wazato\Program.cs @ 12]

StackTraceString: <none>
HResult: 80131500

Nested exception -------------------------------------------------------------
Exception object: 0000000002f28030
Exception type:   Wazato.WazatoException
Message:          わざと例外です
InnerException:   <none>
StackTrace (generated):
    SP               IP               Function
    0000000000DCEE90 00007FF8072208FA Wazato!Wazato.Program.Main(System.String[])+0x6a [H:\Proj\Wazato\Wazato\Program.cs @ 17]

StackTraceString: <none>
HResult: 80131500

0:000> NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\atlmfc.natvis'
NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\ObjectiveC.natvis'
NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\concurrency.natvis'
NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\cpp_rest.natvis'
NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\stl.natvis'
NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\Windows.Data.Json.natvis'
NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\Windows.Devices.Geolocation.natvis'
NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\Windows.Devices.Sensors.natvis'
NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\Windows.Media.natvis'
NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\windows.natvis'
NatVis script unloaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\winrt.natvis'

 

上記の朱色の部分が、関心の高い部分です。スタックトレースが含まれています。

ただ、一部、行数目 (Program.cs @ 12) の特定に不正確さが見られます。


ソースコード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Wazato
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            try
            {
                throw new WazatoException();
            }
            catch (Exception ex)
            {
                throw new Exception("例外が発生しました。", ex);
            }
        }
    }

    public class WazatoException : Exception
    {
        public WazatoException() : base("わざと例外です")
        {

        }
    }
}


因みに、普通に実行した場合のエラー出力はこのようなものです。こちらの行数目の特定は正確です:

H:\Proj\Wazato\Wazato\bin\Debug\Wazato.exe

ハンドルされていない例外: System.Exception: 例外が発生しました。 ---> Wazato.WazatoException: わざと例外です
   場所 Wazato.Program.Main(String[] args) 場所 H:\Proj\Wazato\Wazato\Program.cs:行 17
   --- 内部例外スタック トレースの終わり ---
   場所 Wazato.Program.Main(String[] args) 場所 H:\Proj\Wazato\Wazato\Program.cs:行 21

 

そもそも、アプリがクラッシュする前であれば $exception.ToString() でスタックトレースを取得できます。


dobon.net で紹介されている「AppDomain.UnhandledExceptionイベントを使用する方法
」を用いて、アプリがクラッシュする前に、スタックトレースをどこかへ保存する、という手もあると思いました。

世間のクラッシュ情報回収系ツール (App Center Crashes など) では、このような手法を用いているものと思われます。

 

イベントビューアでは (Application → Windows Error Reporting):

障害バケット 、種類 0
イベント名: CLR20r3
応答: 使用不可
Cab ID: 0

問題の署名:
P1: Wazato.exe
P2: 1.0.0.0
P3: c9a37b6c
P4: Wazato
P5: 1.0.0.0
P6: c9a37b6c
P7: 1
P8: 14
P9: System.Exception
P10:

添付ファイル:
\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERD9ED.tmp.mdmp
\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERDA8A.tmp.WERInternalMetadata.xml
\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERDA9B.tmp.xml
\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERDAA8.tmp.csv
\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERDAD8.tmp.txt

これらのファイルは次の場所にある可能性があります:
\\?\C:\ProgramData\Microsoft\Windows\WER\ReportArchive\AppCrash_Wazato.exe_90677cdd904a7f2b1a386721e7dac5b230783d62_abbc5ab9_2f417abf-d27d-48a1-8f57-3d9dffd9b30e

分析記号:
解決策を再確認中: 0
レポート ID: 06931fdf-f9c9-4609-8100-1ca1b16625a5
レポートの状態: 97
ハッシュされたバケット:
Cab GUID: 0

 

イベントビューアでは (Application → Application Error):

障害が発生しているアプリケーション名: Wazato.exe、バージョン: 1.0.0.0、タイム スタンプ: 0xc9a37b6c
障害が発生しているモジュール名: KERNELBASE.dll、バージョン: 10.0.19041.1706、タイム スタンプ: 0x458acb5b
例外コード: 0xe0434352
障害オフセット: 0x0000000000034fd9
障害が発生しているプロセス ID: 0x6df0
障害が発生しているアプリケーションの開始時刻: 0x01d875b84b1582d2
障害が発生しているアプリケーション パス: H:\Proj\Wazato\Wazato\bin\Debug\Wazato.exe
障害が発生しているモジュール パス: C:\WINDOWS\System32\KERNELBASE.dll
レポート ID: 06931fdf-f9c9-4609-8100-1ca1b16625a5
障害が発生しているパッケージの完全な名前:
障害が発生しているパッケージに関連するアプリケーション ID: 

 

イベントビューアでは (Application → .NET Runtime):

アプリケーション:Wazato.exe
フレームワークのバージョン:v4.0.30319
説明: ハンドルされない例外のため、プロセスが中止されました。
例外情報:Wazato.WazatoException
   場所 Wazato.Program.Main(System.String[])

例外情報:System.Exception
   場所 Wazato.Program.Main(System.String[])

 

CDB と .NET Framework アプリの CPU アーキテクチャ (x86, x64) が異なる場合は "SOS does not support the current target architecture." が出力されます:

0:000> cdb: Reading initial command '!sos.printexception'
SOS does not support the current target architecture.

 

Visual Studio 2022 で .NET Framework 4.x アプリのクラッシュダンプを開く

 Visual Studio 2022 で .NET Framework 4.x アプリのクラッシュダンプを開く

「ファイル」 →「開く」→「ファイル」

右下のファイルタイプを「ダンプ ファイル (*.dmp; *.mdmp; *.hdmp)」にします。

ミニダンプ・完全ダンプ いずれかを開くと概要が表示されます。

つぎに「診断分析の実行」をクリックします。

すると、あたかもデバッグを始めて、デバッグ・ブレークしたかのような画面になります。これで、スタックトレースが得られます。クラッシュ発生の要因に近づけるのではないでしょうか。

勿論、アプリの継続や実行はできません…

[Shift]+[F9] キーで、クイックウォッチを展開しましょう。

例外の詳細を見たい場合は $exception を評価します。

以下はミニダンプ診断時のものです。


「'mscorlib' のメタデータが無効です。ミニダンプをデバッグする場合は、新しいヒープ付きミニダンプを収集し、式を再度評価することによって、この問題を解決できることがあります。」というエラーが幾多表示されます。

以下は完全ダンプ時のものです。


こちらは評価の表示がきちんとできました。


.NET Framework 4.x アプリのクラッシュダンプを作成したい

.NET Framework 4.x アプリのクラッシュダンプを作成したい

レジストリにキーを追加すると、ダンプファイルが得られるようです。

Windows 10 Pro (version 21H2) で確認しました。

参考記事:

以下のレジストリキーの配下に wazato.exe のような exe ファイル名のキーを作成します:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps

詳細は: ユーザーモード ダンプの収集

上図の状態で .reg ファイルをエクスポートするとこのような感じです:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\wazato.exe]
"DumpCount"=dword:00000003
"DumpType"=dword:00000002
"DumpFolder"=hex(2):25,00,50,00,52,00,4f,00,47,00,52,00,41,00,4d,00,44,00,41,\
  00,54,00,41,00,25,00,5c,00,57,00,61,00,7a,00,61,00,74,00,6f,00,00,00
DumpType:

0 = カスタム
1 = ミニ
2 = 完全

レジストリを設定後 .NET Framework のアプリがクラッシュすると .dmp ファイルができました。

クラッシュすると Windows Error Reporting の画面が出現します。
ここで「キャンセル」をクリックして閉じても .dmp は作成されました。

また…
「デバッグ」を選択して、デバッガーが起動し終わった後、
「プログラムの終了」を選択して、アプリを終了した後にも .dmp は作成されました。

単純な容量比較では…

ミニダンプ 11,842 KB
完全ダンプ 102,691 KB

10 倍の差がありました。throw するだけの簡単なコンソールアプリでしたが。

続きはこちら…

 

2021年5月14日金曜日

Microsoft Access フォーム名に「半角カナ」、の件

Access を利用中に、つぎのようなエラーメッセージが表示されたら、疑わしいです…

パターン 1

データベースに含まれている VBA プロジェクトを読み取れないため、データベースを開く事ができません。データベースを開くには VBA プロジェクトを削除する必要があります。VBA プロジェクトを削除するとモジュール、フォーム、およびレポートからすべてのコードが削除されます。

データベースを開いて VBA プロジェクトを削除する前に、バックアップ コピーを作成することをお勧めします。


データベースのバックアップ コピーを作成する場合は、[キャンセル] をクリックしてください。バックアップ コピーを作成しないでデータベースを開き、VBA プロジェクトを削除する場合は、[OK] をクリックしてください。

パターン 2

このデータベース内の VBA モジュールはエラーを含んだ状態で保存された可能性があります。Access ではこのモジュールを回復できますが、まずこのデータベースをバックアップする必要があります。データベースをバックアップするためにこの操作を取り消すには、[キャンセル] をクリックしてください。


バックアップ コピーが既にある場合は、[OK] をクリックしてください。データベースを開くときに、モジュールが正しいかどうか調べてください。正しくない場合は、最新のバックアップに戻してください。

危惧
  • Access によって Access データベースの VBA データが一部損傷され、回復できない可能性
  • バックアップからの復元が必要となる可能性

対策例

回避例

  • msaccess.exe の互換設定を Windows 8 に変更する
  • Windows OS の NLS バージョンを 6.3 から 6.2 に変更する




2019年3月8日金曜日

sqlpackage.exe による localdb への dacpac の展開

C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\150>

sqlpackage.exe ^
 /Action:Publish ^
 /SourceFile:C:\Users\USER\Desktop\DEMO.dacpac ^
 /TargetConnectionString:"Data Source=(localdb)\DEMO;Database=master;"

サーバー '(localdb)\DEMO' 上のデータベース 'master' に公開しています。
配置の初期化中 (開始)
配置の初期化中 (完了)
配置計画の解析中 (開始)
*** プロジェクト データベースとターゲット データベースの照合順序設定が異なるため、配置エラーが発生する可能性があります。
配置計画の解析中 (完了)
データベースの更新中 (開始)
更新が完了しました。
データベースの更新中 (完了)
データベースを正常に発行しました。