none
シャットダウン時に WriteXml を使うとエラー RRS feed

  • 質問

  • 常駐アプリを作成しているのですが、困っていることがあります。よろしくお願いします。

    # 環境:.NET Framework 2.0、Windows XP
    # 言語に依存しない話かもしれません…


    このアプリでは、終了時に下記のようなコードで様々なデータの保存を行っています。
    通常の終了時には問題は発生しないのですが、このアプリを実行したままウィンドウズをシャットダウンすると、次のエラーが発生します。

     

    「csc.exe - アプリケーションエラー
    アプリケーションを正しく初期化できませんでした(0xc0000142)。[OK] をクリックしてアプリケーションを終了してください。」

     

    この時のスタックトレースには、
    「ファイル 'c:\…\LocalSettings\Temp\qq9e4uhi.dll' が見つかりませでした。」
    が出力されていて、その少し前には CodeDom.Compiler などが出力されています。

     

    どうも下記コードの内部的な動作として、コードが動的に作成され、そのコンパイル時にエラーが発生しているように思われます。
    回避する方法はないでしょうか?
    「アプリケーション設定」では、Point 型の値を保存してもエラーにはならないため、何か方法があるのではと考えています。
    # 保存したい値の型は、Point の他にもあります。
    # WM_QUERYENDSESSION 時に下記保存処理を実行しても同じでした。

     

    Code Snippet

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        using (DataTable dt = new DataTable("test"))
        {
            dt.Columns.Add("test", typeof(Point));
            dt.Rows.Add(new Point());
            dt.WriteXml(@"c:\test.dat", XmlWriteMode.WriteSchema);
        }

     

        // これでも同じエラーになります
        //XmlSerializer xs = new XmlSerializer(typeof(Point));
        //using (StreamWriter sw = new StreamWriter(@"c:\test.dat", false))
        //    xs.Serialize(sw, new Point());
    }

     

     

    2008年2月6日 2:22

回答

  • XmlSerializer は、インスタンス生成時に独自のシリアライザクラスを作成し一時フォルダにアセンブリとして出力します。それが原因になってるんでしょう。

    .NET 2.0 の SDK から、sgen.exe というツールが付属するようになりました。上記のクラス出力を事前コンパイルするためのものです。これを使用して事前にアセンブリを作成し、アプリケーションはそれを参照して XmlSerializer の代わりにそっちのシリアライザを使用してシリアライズするようにすればいいでしょう。

    2008年2月6日 2:50
  • シャットダウン中に動的コンパイルが走らないようにすれば良いと思います。

    選択肢としては2つ考えられます。

     

    1.シリアライズの対象になる型についてプリコンパイルしておく。

    下記のスレッドを参照してください。

    http://forums.microsoft.com/msdn-ja/ShowPost.aspx?PostID=1893911&SiteID=7

     

    2.シリアライズ対象となる型について逆シリアライズやダミーのシリアライズを行っておく。

    XmlSerializerの動的コンパイル結果はキャッシュされるはずですので、アプリ起動直後のタイミングで対象の型についてダミーのシリアライズを行っておけば、良いのかもしれません。

    2008年2月6日 23:01
    モデレータ

すべての返信

  • こんにちは

    RockyRockyと申します。

     

    コードをそのまま貼り付けて実行しましたが、

    エラーは起きませんでした。

     

    その他の部分に問題はありませんか?

    2008年2月6日 2:35
  • XmlSerializer は、インスタンス生成時に独自のシリアライザクラスを作成し一時フォルダにアセンブリとして出力します。それが原因になってるんでしょう。

    .NET 2.0 の SDK から、sgen.exe というツールが付属するようになりました。上記のクラス出力を事前コンパイルするためのものです。これを使用して事前にアセンブリを作成し、アプリケーションはそれを参照して XmlSerializer の代わりにそっちのシリアライザを使用してシリアライズするようにすればいいでしょう。

    2008年2月6日 2:50
  • シャットダウン中に動的コンパイルが走らないようにすれば良いと思います。

    選択肢としては2つ考えられます。

     

    1.シリアライズの対象になる型についてプリコンパイルしておく。

    下記のスレッドを参照してください。

    http://forums.microsoft.com/msdn-ja/ShowPost.aspx?PostID=1893911&SiteID=7

     

    2.シリアライズ対象となる型について逆シリアライズやダミーのシリアライズを行っておく。

    XmlSerializerの動的コンパイル結果はキャッシュされるはずですので、アプリ起動直後のタイミングで対象の型についてダミーのシリアライズを行っておけば、良いのかもしれません。

    2008年2月6日 23:01
    モデレータ
  • RockyRocky さん、検証ありがとうございます。
    「その他の部分」はなく、上のコードだけで発生します。
    書き忘れていましたが、Framework2.0 には sp1 を当てられていません…
    RockyRocky さんの環境では、シャットダウン時にエラーにならないのでしょうか?

     

    Hongliang さん、レスありがとうございます。

     Hongliang さんからの引用
    XmlSerializer は、インスタンス生成時に独自のシリアライザクラスを作成し一時フォルダにアセンブリとして出力します。

    アセンブリが作成されるのはインスタンスの生成時なんですね。Serialize メソッドの呼び出し時だと思いこんでいました。
    そこで、試しに XmlSerializer のインスタンスの生成は事前に行っておき、FormClosed では Serialize の実行のみ行うようにしてみたところ、エラーが出なくなりました!!
    残念ながら、DataTable では同じようにはできませんでした。WriteXml メソッドの実行時にシリアライズが行われ、その際、キャッシュはなされないようです。
    そこで、自分で XmlSerializer でシリアライズした結果を文字列として DataTable に格納しようと思います。

     

    Azulean さん、レスありがとうございます。
    1 の方ですが、Hongliang さんに書いていただいた sgen については全く知らなかったので調べようと思っていたのですが、具体的なことがわかり助かりました。

    # 解決策がわかったので、実は、sgen は調べなくてもいいかなって思ってた所でした(^^;;
    2 の方は、上述の通りでした。

     

    RockyRocky さんの件、気になりますが、取りあえず回答済みにさせていただきます。
    # RockyRocky さんには付けなくてすいません。お手数おかけしました。
    ありがとうございました。

    2008年2月7日 0:29
  •  TH01 さんからの引用

    RockyRocky さん、検証ありがとうございます。
    「その他の部分」はなく、上のコードだけで発生します。
    書き忘れていましたが、Framework2.0 には sp1 を当てられていません…
    RockyRocky さんの環境では、シャットダウン時にエラーにならないのでしょうか?

     

    ごめんなさい。

    実行条件を勘違いしていました。

    OSをシャットダウンするんですね。

    お騒がせいたしました。

    2008年2月8日 4:56
  • いえいえ、了解しました。ありがとうございました。
    2008年2月12日 2:48