0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

XmlSerializerを使うと全く関係のない箇所でDllImport属性が失敗する

Posted at

XmlSerializerを使うと全く関係のない箇所でDllImport属性が失敗する

※注意 完全に原因が分かったわけではないが、なぜかこうするとうまくいく系の備忘録です。

アプリの構成
a.exe ← C#
b.dll ← C#
c.dll ← C++

a,b,c全部自作のものであるとする。

実装

  1. aの中にXmlSerializerを使った処理を書く
  2. bの中でcのメソッドをDllImportを使って書く
  3. c内にはstdcallの_declspec(dllexport)で適当な処理を書いておく

デバッグした時の流れ

  1. b.dll、c.dllがロードされる
  2. アプリケーションの設定としてxmlに保存していたのをアプリケーションの最初の方で読みだす
  3. ここでXmlSerializerのコンストラクタ内でFileNotFoundExceptionが発生する(シリアライズのためのDLLを作成するオプションがオフのため作ってない)
  4. 内部的にはそのまま例外処理が行われるのでアプリケーション側ではそのまま処理が続行する
  5. ここでなぜかc.dllがアンロードされる
  6. その後aからbのメソッドを呼ぶ
  7. bはcのラッパーライブラリなので内部的にはDllImport属性のついたメソッドをそのまま呼ぶ
  8. DllNotFoundException無効なアドレスにアクセスしようとしています。という例外が発生して落ちる

対処法

その1

XmlSerializerを使う処理の前にDllImport属性のついたメソッドを読んでおく。
一回呼んでおくとアンロードされないっぽい。

その2

XmlSerializerのコンストラクタ内でFileNotFoundExceptionを発生させないためにシリアライズ用のDLLを作成しておく。

以下Copilotに質問した時の返答

  1. DLL の生成オプションを有効にする:
    プロジェクトのプロパティからビルド設定に移動します。
    「シリアル化アセンブリの生成」オプションをオンにします。
    これにより、必要な DLL が生成されます。
  2. csproj ファイルを直接編集する:
    csproj ファイル内に false を追加します。
    このオプションは UI で設定できないため、直接ファイルを編集する必要があります。
  3. ビルド後イベントで sgen.exe を呼び出す:
    sgen.exe を呼び出して DLL を生成する方法もあります。
    Visual Studio のインストール環境によっては、ビルド後イベントのパスを調整する必要があるかもしれません。

私は1だけだと作成されなかったので2も行う必要がありました。特殊事例のためおま環の可能性が高いです。
dllがアンロードされる原因まではわからなかったのでもしかすると他の要因でダメになってるのかも・・・。

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?