プログラムを作っていて設定を保存するためのクラスを作ったのですが原因不明のエラーが出てきてしまいます。
Public Class cde_config
Const CONFIG_FILE As String = "config.xml"

Public FolderName As String
Public exex As New ArrayList

Public Sub New()
If File.Exists(CONFIG_FILE) Then
Dim serializer As XmlSerializer = New XmlSerializer(GetType(cde_config))
Dim stream As FileStream = New FileStream(CONFIG_FILE, FileMode.Open)
Try
Me.FolderName = CType(serializer.Deserialize(stream), cde_config).FolderName 'ここでエラーが発生
Me.exex = CType(serializer.Deserialize(stream), cde_config).exex
Finally
stream.Close()
End Try
Else
FolderName = "略"
exex.Add(New String("略"))
End If
End Sub
Public Sub save()
Dim serializer As XmlSerializer = New XmlSerializer(GetType(cde_config))
Dim stream As FileStream = New FileStream(CONFIG_FILE, FileMode.Create)
Try
serializer.Serialize(stream, Me)
Finally
stream.Close()
End Try
End Sub
End Class

エラーの内容は
'System.InvalidOperationException' のハンドルされていない例外が system.xml.dll で発生しました。
追加情報 : XML ドキュメント (2,2) でエラーが発生しました。
です。
どこに問題があるのでしょうか。

A 回答 (2件)

すみません.私のところでもう一回実行してみましたが,やはり出ました...



ソースにブレークポイントを適当に設定して追ってみました.
すると,推測ですが,
serializer.Deserialize(stream), cde_config)
XmlSerializerがデシリアライズする際,↑の第2引数の型でインスタンス生成をしている為,
cde_configのデフォルトコンストラクタが呼ばれて例外が発生しているみたいです.

設定情報を保持するクラスと,読込・保存を行うクラスを別にする方法しか思いつきませんでした...
蛇足ですが,私がコンソールアプリケーションで試しに作ってみたソースを貼っておきます.
お役に立てなくてすみません.

====================================================
Imports System.IO

Module Module1

Sub Main()
Dim cls As cde_config

Try
If File.Exists(cde_config.CONFIG_FILE) Then
Console.WriteLine("File:" + cde_config.CONFIG_FILE + "が見つかりました.")
Console.WriteLine("File:" + cde_config.CONFIG_FILE + "を読込みます.")

cls = cde_config_Reader.read()

Console.WriteLine("File:" + cde_config.CONFIG_FILE + "を読込みました.")
Else
Console.WriteLine("File:" + cde_config.CONFIG_FILE + "が見つかりません.")
Console.WriteLine("File:" + cde_config.CONFIG_FILE + "を生成します")

cls = New cde_config
cls.FolderName = "test"
cls.exex.Add("TEST")
cde_config_Reader.save(cls)

Console.WriteLine("File:" + cde_config.CONFIG_FILE + "を生成しました.")
End If

Console.ReadLine()

Catch ex As Exception

End Try

End Sub

End Module

Public Class cde_config

Public Sub New()
Me.exex = New ArrayList
End Sub

Public Const CONFIG_FILE As String = "config.xml"
Public FolderName As String
Public exex As ArrayList

End Class

Public Class cde_config_Reader

'シリアライズ
Public Shared Sub save(ByVal cls As cde_config)

Dim fs As System.IO.FileStream

Try
'XmlSerializerオブジェクトを作成
'書き込むオブジェクトの型を指定する
Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(cde_config))
'ファイルを開く
fs = New System.IO.FileStream(cde_config.CONFIG_FILE, System.IO.FileMode.Create)
'シリアル化し、XMLファイルに保存する
serializer.Serialize(fs, cls)

Catch ex As Exception
Throw ex
Finally
If Not IsNothing(fs) Then fs.Close()
End Try

End Sub

'デシリアライズ
Public Shared Function read() As cde_config

Dim fs As System.IO.FileStream
Dim cls As cde_config

Try
If Not File.Exists(cde_config.CONFIG_FILE) Then
Return Nothing
End If

'XmlSerializerオブジェクトの作成
Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(cde_config))
'ファイルを開く
fs = New System.IO.FileStream(cde_config.CONFIG_FILE, System.IO.FileMode.Open)
'XMLファイルから読み込み、逆シリアル化する
cls = CType(serializer.Deserialize(fs), cde_config)

Return cls

Catch ex As Exception
Throw ex
Finally
If Not IsNothing(fs) Then fs.Close()
End Try

End Function
End Class
    • good
    • 0

恐らくシリアライズ


がうまくいっていないのでは.
(Public Sub save()の
 serializer.Serialize(stream, Me)かな?)

どぼん様を参考にやってみましたが,こんな感じですか?
==================================
Imports System.IO

Public Class cde_config
Const CONFIG_FILE As String = "config.xml"

Public FolderName As String
Public exex As ArrayList

Public Sub New()

Try
Dim cls As cde_config = Me.read()
If Not IsNothing(cls) Then
'ファイルが存在した時
Me.FolderName = cls.FolderName
'…
Else
'ファイルが存在しない時
Me.FolderName = "略"
'設定した値を保存するとか…
Me.save()
'…
End If
Catch ex As Exception
Throw ex
End Try

End Sub

'ファイルが無い時用コンストラクタ
Private Sub New(ByVal clar As Boolean)
If clar Then
Me.FolderName = ""
Me.exex = New ArrayList
End If
End Sub

'シリアライズ
Private Sub save()

Dim fs As System.IO.FileStream
Dim cls As cde_config = New cde_config(True)

Try
cls.FolderName = "test"
'XmlSerializerオブジェクトを作成
'書き込むオブジェクトの型を指定する
Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(cde_config))
'ファイルを開く
fs = New System.IO.FileStream(Me.CONFIG_FILE, System.IO.FileMode.Create)
'シリアル化し、XMLファイルに保存する
serializer.Serialize(fs, cls)

Catch ex As Exception
Throw ex
Finally
If Not IsNothing(fs) Then fs.Close()
End Try

End Sub

'デシリアライズ
Private Function read() As cde_config

Dim fs As System.IO.FileStream
Dim cls As cde_config

Try
If Not File.Exists(Me.CONFIG_FILE) Then
Return Nothing
End If

'XmlSerializerオブジェクトの作成
Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(cde_config))
'ファイルを開く
fs = New System.IO.FileStream(Me.CONFIG_FILE, System.IO.FileMode.Open)
'XMLファイルから読み込み、逆シリアル化する
cls = CType(serializer.Deserialize(fs), cde_config)

Return cls

Catch ex As Exception
Throw ex
Finally
If Not IsNothing(fs) Then fs.Close()
End Try

End Function
End Class

参考URL:http://dobon.net/vb/dotnet/file/xmlserializer.html
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

やってみましたが同じエラーが出ます。
シリアライズするとちゃんとXMLファイルが作成され、中身もXMLの文法的にはまったく問題ないものができています。

お礼日時:2005/04/22 18:10

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qフルパスから最後のディレクトリ名を取得したい。

vb.netなのですが、例えば
c:\aaa\bbb\ccc\ddd\eee\fff.exe
というフルパスがあったとして、
eeeというディレクトリ名を取得したいのですが、
何か良い方法はないでしょうか。
それぞれのディレクトリ名の文字数や階層数は
決まっていないのですが、オススメの方法が
ありましたら、教えて頂けると助かります。

Aベストアンサー

MessageBox.Show(IO.Path.GetFileName(IO.Path.GetDirectoryName(myPath)))

IO.Path の GetDirectoryName でフォルダのフルパスを取得して、さらに IO.Path の GetFileName で最終フォルダ(またはファイル)の名前を取得。

QC#で共有変数の定義をするには

C#で共有変数の定義をするには、どうしたらよいでしょうか。具体的には、起動パラメータで、任意の文字列(3~4バイト)を渡して、C#アプリケーションを、起動し、プログラムの任意の場所で、そのパラメータを参照したいと考えています。起動パラメータの受け取りは、できるのですが、そのパラメータを、プログラムのどこからも参照できる領域(ここの定義方法が不明)に格納するには、どうしたらよいでしょうか。(2重起動を許す前提です。実行時に1つの目のプログラムにはパラメータ"XYZ"を渡し、2つ目のプログラムを起動時にはパラメータ"ABCD"を渡し、その値により、プログラムの動作を制御したいと思っています)
Windows-xp visual-studio2008 C#でwindowsアプリケーションを作成しています。

Aベストアンサー

namespace test1
{
  static class Program
  {
    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
      if (args.Length > 0)
      {
        strArg = args[0];
      }
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new Form1());
    }
    // ここに記述
    static public string strArg = null;
  }
}

メインクラスのメンバーとしてスコープが有効な場所に記述します

namespace test1
{
  static class Program
  {
    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
      if (args.Length > 0)
      {
        strArg = args[0];
      }
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(n...続きを読む

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。

Qbatである文字列内に特定の文字列が含まれているか確認したい

batファイルの中である変数「abc」の中に「test」という文字が含まれていたら○○を行なうという分岐を作成したいのですが、どのように行なえばよいのでしょうか?

そのまま、ずばりのお答えお待ちしております。

よろしくお願い致します。

Aベストアンサー

大文字小文字を区別しなくていいなら、

if not "%abc:test=%" == "%abc%" echo 含まれていた

区別するなら、

echo %abc% | find "test" >NUL
if not ERRORLEVEL 1 echo 含まれていた

QC#でのProcess.Startと変数path

C:\Program Files\a\にa.exeがあって、a.exeにパスが通っていて、
C:\> a.exe
でaが実行できる状態にあるのですが、

System.Diagnostics.Process.Start("a");

でなぜか
An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in System.dll

Additional information: 指定されたファイルが見つかりません。

と言われ実行できません。
a.exeをパスを指定しないで実行するにはどうしたらいいのでしょうか。

Aベストアンサー

>System.Diagnostics.Process.Start("a");

拡張子指定したらどうです?

http://msdn.microsoft.com/ja-jp/library/53ezey2s%28v=vs.100%29.aspx
って、拡張子ナシでもOKとはなっていますねぇ…。
>同様に、[ファイル名を指定して実行] ダイアログ ボックスで実行可能ファイル名は拡張子 .exe が付いているかどうかに関係なく受け入れられるのと同じように、fileName パラメーターでも拡張子 .exe は省略できます。
と……。

ということで、「ファイル名を指定して実行」でaだけで起動できます?

>システムでパス変数を引用符で囲んで宣言している場合は、その場所で見つかったプロセスを開始するときに、そのパスの絶対パスを指定する必要があります。 これを実行しないと、システムはパスを見つけることができません。
って書かれているのが微妙…ですかねぇ。
"Program Files"ってことで、""でくくっているでしょうし。
# path設定の方をショートファイルネームにしたらどうなりますかね?

>System.Diagnostics.Process.Start("a");

拡張子指定したらどうです?

http://msdn.microsoft.com/ja-jp/library/53ezey2s%28v=vs.100%29.aspx
って、拡張子ナシでもOKとはなっていますねぇ…。
>同様に、[ファイル名を指定して実行] ダイアログ ボックスで実行可能ファイル名は拡張子 .exe が付いているかどうかに関係なく受け入れられるのと同じように、fileName パラメーターでも拡張子 .exe は省略できます。
と……。

ということで、「ファイル名を指定して実行」でaだけで起動できます?

>システムでパス...続きを読む

QC#で起動時のフォームを非表示にした後、Showで表示したいのですが

VS2013 Comunity C#を使っています。
起動後のフォームを非表示にした後、何らかのイベントでフォームを表示させようとしています。
マイクロソフトの以下の頁を参考にしたら、うまくいったのですが、
//-----------------------------------------------------------------
方法 : スタートアップ Windows フォームを非表示にする
https://msdn.microsoft.com/ja-jp/library/754w18dd(v=vs.110).aspx
//-----------------------------------------------------------------

次のサイトには、「System.Windows.Forms.Loadイベントは一度だけとは限らない」と書いてあります。
http://d.hatena.ne.jp/Kazzz/20070913/p4

今後、プログラムを作っていったときに、都合が悪くならないように以下のようにShow()を使うように書き換えたのですが、メッセージボックスのOKを押した後、フォームを表示せずに終了してしまいます。
なぜなんでしょうか?
書き換える前にはフォームは正常に表示されます。
//********************************************
class MainApplication
{
public static void Main()
{
// Form1 f1 = new Form1();//MS code
Form1 f1 = new Form1();//変更
System.Windows.Forms.MessageBox.Show("The application "
+ "is running now, but no forms have been shown.");
f1.Text = "Running Form";

// f1.ShowDialog();//MS code
f1.Show();//変更

}
}
//*******************************************

VS2013 Comunity C#を使っています。
起動後のフォームを非表示にした後、何らかのイベントでフォームを表示させようとしています。
マイクロソフトの以下の頁を参考にしたら、うまくいったのですが、
//-----------------------------------------------------------------
方法 : スタートアップ Windows フォームを非表示にする
https://msdn.microsoft.com/ja-jp/library/754w18dd(v=vs.110).aspx
//-----------------------------------------------------------------

次のサイトには、「System.Wi...続きを読む

Aベストアンサー

>メッセージボックスのOKを押した後、フォームを表示せずに終了してしまいます。

表示した瞬間にプロセスが終了したのでしょう。

>// f1.ShowDialog();//MS code

https://msdn.microsoft.com/ja-jp/library/c7ykbedk%28v=vs.110%29.aspx
『 このメソッドが呼び出されると、次に続くコードは、ダイアログ ボックスが閉じるまで実行されません。』
ということで、ダイアログ(フォーム)を閉じるまでそこから先(Main()の終わり)までは進みません。

>f1.Show();//変更

『表示』するだけです。
表示に関して関連するコードは実行されるでしょうが、それだけです。
https://msdn.microsoft.com/ja-jp/library/39wcs2dh%28v=vs.110%29.aspx

フォーム上のコントロールに対しての操作を継続することもできません。
で、「表示した後、即プロセス終了」ではフォームに対して強制的に閉じる処理が呼び出されるかと思われます。
# フォームのデストラクタが呼ばれる…でしょうね。


ということで、やりたいことはなんですか?
f1.Show()でなければならないのであれば、それ相応の処理を自前でやる必要がありますが…。
# C#でメッセージループを処理…ですかね?

>メッセージボックスのOKを押した後、フォームを表示せずに終了してしまいます。

表示した瞬間にプロセスが終了したのでしょう。

>// f1.ShowDialog();//MS code

https://msdn.microsoft.com/ja-jp/library/c7ykbedk%28v=vs.110%29.aspx
『 このメソッドが呼び出されると、次に続くコードは、ダイアログ ボックスが閉じるまで実行されません。』
ということで、ダイアログ(フォーム)を閉じるまでそこから先(Main()の終わり)までは進みません。

>f1.Show();//変更

『表示』するだけです。
表示に関して関連す...続きを読む

Q特殊記号が勝手にエスケープされてしまう

Windows2000 ServerにおいてVBScriptとMicrosoft.XMLDOMを用いてASPスクリプトを作成しています。

XMLで特殊文字<,>,",',&を扱う際には&lt;,&gt;,&quot;,&apos;に置換しなくてはならない事はわかったんですが、
実際にReplaceすると例えば&lt;が&amp;lt;になってしまいます。
置換する順番を変えてもこうなるのでおかしいと重い、&amp;への置換を止めてもです。
しかもこれは読み出すと何事も無かったかのように&amp;lt;が&lt;へと戻っています。

試しに置換を全く行わない状態で
「テスト&'>"」という文字列を保存してみると、
保存先ファイルの中では「テスト&amp;'&gt;&quot;」という状態になっていました。

恐らく&,<,>,"が勝手に置換され、読み出される時には元に戻す処理が行われていると思うんですが、これがどの部分で行われているのかがよくわかりません。
JavaScriptで読み出した際にも同様に復元されていたようなので、MSXMLの仕様なのかなと思うんですが、それを裏付ける資料を見つける事もできませんでした。

XMLにおける特殊記号の扱いについて書いているサイトにも記述が見つからなかったので、もしかしたら凄く基本的な事だったりおかしな質問だったりするのかもしれませんが、ご存知の方がいらっしゃいましたら是非ご教授願いたいです。
参考URLだけでも良いですのでどうかよろしくお願いします。

Windows2000 ServerにおいてVBScriptとMicrosoft.XMLDOMを用いてASPスクリプトを作成しています。

XMLで特殊文字<,>,",',&を扱う際には&lt;,&gt;,&quot;,&apos;に置換しなくてはならない事はわかったんですが、
実際にReplaceすると例えば&lt;が&amp;lt;になってしまいます。
置換する順番を変えてもこうなるのでおかしいと重い、&amp;への置換を止めてもです。
しかもこれは読み出すと何事も無かったかのように&amp;lt;が&lt;へと戻っています。

試しに置換を全く行わない状態で
「テスト&'>"」という...続きを読む

Aベストアンサー

#2>node.attributes.item(0).nodeValue = "test>"
node.attributes.item(0).nodeValue = "test<"
の間違いですね

>MSXMLの仕様なのかなと
MSXMLのリファレンスで

According to the W3C DOM specification, an XML parser can completely expand entity references into entities before the structure model is passed to the DOM. When these entity references are expanded, the document tree does not contain any entity references.

When Microsoft&reg; XML Core Services (MSXML) validates the XML document, it expands external entities (except binary entities). The nodes representing the expanded entity are available as read-only children of the entity reference. The Microsoft implementation does not expand these entities when it is not validating.

とあるので、仕様かと思います。
(英語力が低いので、何ですが、W3C DOM の求めるところで、XMLパーサーは、DOMに変換するにあたってエンティティの展開をするべきということかな?、なんにしても、XMLパーサーとしては、変換するか、エラーにするかしないといけませんが、エラーにしてたら使い勝手の悪いものになると思います。)
ちなみに、
xmlDoc.createEntityReference("lt")
のようにして&lt;エンティティを作成できます。

#2>node.attributes.item(0).nodeValue = "test>"
node.attributes.item(0).nodeValue = "test<"
の間違いですね

>MSXMLの仕様なのかなと
MSXMLのリファレンスで

According to the W3C DOM specification, an XML parser can completely expand entity references into entities before the structure model is passed to the DOM. When these entity references are expanded, the document tree does not contain any entity references.

When Microsoft&reg; XML Core Services (MSXML) vali...続きを読む

QC#にて別クラスの関数を使いたい

C#にて、別クラスの関数を使用する方法を教えてほしいです。

下記のような、構造体を受け取るメソッドを作りました。

*****************************
private struct MyPoint
{
public int x;
public int y;
}

private void proc1(MyPoint pt)
{
MessageBox.Show("座標:" ; pt.x + "," + pt.y + "実行結果");
}

private void button1_Click(object sender ,System.EventArgs e)
{

MyPoint pt;
pt.x = 10;
pt.y = 20;
proc(pt);
}
*****************************

別のフォームのクラスから、proc1を呼び出したいのですが、やり方がわかりません。
どうか、教えてください。

Aベストアンサー

同じ定義をしたとしても別の名前空間に書いた構造体は同一とはみなされません。

呼び出し先クラスでの構造体を private では無く、public で宣言して下さい。

呼び出し元では、

MyClass.MyPoint pt;

のようにして実体を作ります。

QSQLServer2005上の別DBからテーブルを読みたい

SQLServer2005で2つの異なるデータベース(ADB、BDB)が存在します。
ADBでBDBにあるテーブルを取得して検索をかけたいのですが、どのようにすれば実現できるのでしょうか。
BDBのVIEWを作成するイメージなんですが、リンクテーブルを設定するとかが必要になるのですか。
もしそうだとしたら、どうリンクテーブルを設定するのか教えてください。

Aベストアンサー

その2つのデータベースは同じインスタンスにいますか?
同じインスタンスにいるなら、
SELECT * FROM BDB.dbo.テーブル名
などで検索できます。

インスタンス自体が別ならリンクサーバを設定します。
サーバのリンク
http://msdn.microsoft.com/ja-jp/library/ms188279(SQL.90).aspx

もしくはアドホックリモートクエリを使う方法もあります。
ただし、OPENROWSETを使う場合は「SQL Server のセキュリティ構成」で利用を許可しないといけませんのでご留意ください。

QXMLからデータを取得

いつもお世話になっております。

XMLファイルに含まれたデータの中から、特定のデータを検索するプログラムを作りたいと思っております。

<AAA Name="テスト">
   <BBB x="2" y="2"></BBB>
   <CCC Num="0001"></CCC>
   <CCC Num="0002"></CCC>
</AAA>
XMLデータの形式は↑みたいな感じで、これが100以上あり、CCCタグは0~5個までです。

フォームにテキストボックスを配置し、そこに検索したい語句を入れ、
AAAタグのNameの中身と合致したら、BBB、CCCの属性をすべて取得して表示するということをしたいのですが、
どうにも上手くいきません。

VB2008を使用しております。
方法をご存知の方、ご教授ください……orz

Aベストアンサー

a_navi.Select("//AAA[@Name='test']")
で AAAタグの検索条件を増やさないのであれば

xml_data = a_navi.Select("//AAA[@Name='test']")
while xml_data.MoveNext
  Dim xmldoc As New Xml.XmlDocument
  ' XMLDocumentに 選択されたCurrentのOuterXmlを与えれば
  ' 自前で XML形式の体裁を整える必要がありません
  xmldoc.loadXML( xml_data.Current.OuterXml)
  ' StringReaderにも OuterXmlで与えます
  a_xml = new Xml.XmlTextReader(New IO.StringReader(xml_data.DocumentElement.OuterXml))
  while a_xml.Read
    If a_xml.NodeType = XmlNodeType.Element Then
      Select Case a_xml.LocalName
        ' AAAタグ用の分岐を定義
        Case "AAA"
          Console.WriteLine("aaa:" & a_xml.GetAttribute("age") & "," & a_xml.GetAttribute("id"))
        Case "BBB"
          Console.WriteLine("bbb:" & a_xml.GetAttribute(0) & "," & a_xml.GetAttribute(1))
        Case "CCC"
          Console.WriteLine("ccc:" & a_xml.GetAttribute(0))
      End Select
    End If
  end while
end while

といった具合でよさそうですよ

a_navi.Select("//AAA[@Name='test']")
で AAAタグの検索条件を増やさないのであれば

xml_data = a_navi.Select("//AAA[@Name='test']")
while xml_data.MoveNext
  Dim xmldoc As New Xml.XmlDocument
  ' XMLDocumentに 選択されたCurrentのOuterXmlを与えれば
  ' 自前で XML形式の体裁を整える必要がありません
  xmldoc.loadXML( xml_data.Current.OuterXml)
  ' StringReaderにも OuterXmlで与えます
  a_xml = new Xml.XmlTextReader(New IO.StringReader(xml_data.DocumentElement...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報