C#でiniファイルの書き込みがうまくいかない理由

このQ&Aのポイント
  • C#初心者がINIファイルの書き込みに問題を抱えています。
  • INIファイルの生成は成功しているが、書き込みができず空ファイルとなってしまう。
  • 解決方法を教えてください。
回答を見る
  • ベストアンサー

C#でiniファイルの書き込みがうまくいきません。

C#初心者です。今回INIファイルを生成→書き込みを行うためのソースコードを書いたのですが、空ファイルの生成はうまくいくのにINIファイルへの書き込みがうまくいかず、空ファイルのままになってしまいます。なぜでしょうか? 以下ソースコード using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; using System.Runtime.InteropServices; namespace Loei_Server_ { /* ネットで公開されていたINIファイルに関するクラス。 難しいことは考えちゃアカン。 */ class IniFileHandler { [DllImport("KERNEL32.DLL")] public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName); [DllImport("KERNEL32.DLL", EntryPoint = "GetPrivateProfileStringA")] public static extern uint GetPrivateProfileStringByByteArray(string lpAppName, string lpKeyName, string lpDefault, byte[] lpReturnedString, uint nSize, string lpFileName); [DllImport("KERNEL32.DLL")] public static extern uint GetPrivateProfileInt(string lpAppName, string lpKeyName, int nDefault, string lpFileName); [DllImport("KERNEL32.DLL")] public static extern uint WritePrivateProfileString( string lpAppName, string lpKeyName, string lpString, string lpFileName); } class Program { static void Main(string[] args) { /* 日付を取得。 */ DateTime this_time = DateTime.Now; /* 多重起動するとマズイので多重起動していたら強制的に終了する。*/ if (System.Diagnostics.Process.GetProcessesByName(System.Diagnostics.Process.GetCurrentProcess().ProcessName).Length > 1) { Console.WriteLine(" [Error] " + "[" + this_time.ToString() + "] Application already has started. This program is on the nature, you can not multi-boot."); return; } /* コンフィグデータの確認。なかったら勝手に生成する。 */ if (!File.Exists("Config.ini")) { Console.WriteLine(" [Warning] " + "[" + this_time.ToString() + "] Config.ini file could not be found. I created you."); /* 空のINIファイルを生成。 */ StreamWriter writer = new StreamWriter("Config.ini", true); /* 生成したINIファイルにいろいろ書き込む。 */ IniFileHandler.WritePrivateProfileString("Loei_Server_", "TCP_IP", "localhost", "Config.ini"); IniFileHandler.WritePrivateProfileString("Loei_Server_", "TCP_HOST", "25565", "Config.ini"); Console.WriteLine(" [Info] " + "[" + this_time.ToString() + "] It has generated an Config.ini file!"); }

質問者が選んだベストアンサー

  • ベストアンサー
  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.2

No1です 編集ミスってました WritePrivateProfileString はそれだけでファイルの作成・書き込み・クローズを行いますので (WindowsAPIです) >StreamWriter writer = new StreamWriter("Config.ini", true); とか言ったことを自前で行う必要がありません Console.WriteLine との組み合わせで作成されたファイル 上書きしてるのではないでしょうか ReadPrivateProfile の時はファイルが無ければデフォルト値がセットされます(パラメータ) ほとんど必要ないと思いますが 関数の戻り値で正常かを判断する必要はあるかもしれません

Chespin
質問者

お礼

ご回答有難うございます。この後いろいろ試したのですが、ビルドエラーになったり、INIファイルが生成されなかったりして心が折れました。 よく考えたらXMLファイルを使ってもよかったですね。

その他の回答 (1)

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.1

WritePrivateProfileString はそれだけでファイルの作成・書き込み・クローズを行いますので ReadPrivateProfile の時ファイルが無ければデフォルト値がセットされます(パラメータ) >StreamWriter writer = new StreamWriter("Config.ini", true); とか言ったことを自前で行う必要がありません Console.WriteLine との組み合わせで作成されたファイル 上書きしてるのではないでしょうか ほとんど必要ないと思いますが 関数の戻り値で正常かを判断する必要はあるかもしれません

関連するQ&A

  • C# パラメータが消える

    以下の様に 共通変数クラスSystemStartDEC を作成し、変数セットまではできてますが Login_Loadでは変数がクリアされています。 なぜでしょうか? public Login() { InitializeComponent(); Login_Load(); this.BtnCancel.Click += new System.EventHandler(this.BtnCancel_Click); this.BtnLogin.Click += new System.EventHandler(this.BtnLogin_Click); } private void Login_Load() { string[] strParam; //iniファイル読込 if (InspecTool004_02.GetIni(this.lVerComVal) == false) { clsEnc.DeleteFile(strSettingIniName); MessageBox.Show("INIファイルの読み込みに失敗しました。" + "/r/n" + "終了します。"); return; } } public class InspecTool004_02 { class IniFileHandler { [DllImport("KERNEL32.DLL")] public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName); [DllImport("KERNEL32.DLL", EntryPoint="GetPrivateProfileStringA")] public static extern uint GetPrivateProfileStringByByteArray(string lpAppName, string lpKeyName, string lpDefault, byte [] lpReturnedString, uint nSize, string lpFileName); [DllImport("KERNEL32.DLL")] public static extern uint GetPrivateProfileInt( string lpAppName, string lpKeyName, int nDefault, string lpFileName ); [DllImport("KERNEL32.DLL")] public static extern uint WritePrivateProfileString( string lpAppName, string lpKeyName, string lpString, string lpFileName); [DllImport("winmm.dll")] public static extern uint timeGetTime(); } //INIファイル読み込み public static Boolean GetIni(SystemStartDEC.strCom lVerComVal ) { StringBuilder sb_1 = new StringBuilder(1024); string strIniName ; string strBuffer ; Boolean bRtn ; strIniName = ".\\" + SystemStartDEC.strCom.SettingIniName; //DB Section IniFileHandler.GetPrivateProfileString("DB", "ConStr", "default", sb_1, sb_1.Capacity, strIniName); if( sb_1.ToString() == "default" ) { MessageBox.Show("SettingINIファイルDBセクションのConStrが読めません。"); return false; } lVerComVal.IniParam.DBStr = sb_1.ToString(); } public class SystemStartDEC { ////// <summary> ////// 全体共通 ////// </summary> ////// <remarks></remarks> public struct strCom { public strIniParam IniParam; public strUserInfo UserInfo ; public strDispInfo DispInfo ; public strMailInfo MailInfo ; } }

  • C#のDllImportでuint型をどう指定すればいいのでしょうか?

    [DllImport("User32.dll")] public static extern IntPtr GetNextWindow(IntPtr hWnd,uint wCmd);の uint wCmdに GW_HWNDNEXTを指定したいのですがどのような 書き方で指定したらいいのでしょうか? よろしくお願いいたします

  • VB2008 iniファイルの全セクション取得方法

    こんばんわ。iniファイルの全セクションを取得したく、 以下のコードを使うことはわかったのですが、ここから先がVB初心者の為全く解かりません。ボタン1を押したらC:\Test.ini のファイルの全セクションを取得というコードはどのように記入すればよいのでしょうか。 どうぞ宜しくお願いいたします。 Declare Function GetPrivateProfileSectionNames Lib "Kernel32.dll" _ Alias "GetPrivateProfileSectionNamesA" _ (ByVal lpszReturnBuffer As String, ByVal nSize As Long, _ ByVal lpFileName As String) As Long

  • C#の仕様諸々について

    諸事情あって 数時間前 初めてC#の仕様に触れ、初めて実際にいじってみました。 で、細かいとこ全然違うなーとか思いながら 色々と考えてみたのですが とりあえずこれ CやC++での#include とかに当たるものが何も書かずに自動化されてる、ような感じでしょうか この仕様だと 数万行程度の規模のプログラムだったら良いかもしれませんが もっと増えて仮に10万行越えるとかくらいになってくると、開発環境がちゃんと反応できるか心配です。 そう言う場合って 仮に個人で作るとして 尚且つC++だったら普通動的ロードしないような必須機能であったとしても やっぱりアセンブリの分割を(別途dllに)するのが良いということになるのでしょうか? またinternalを使った場合 外部のアセンブリから使えない→開発環境に自動チェックされる量を減らせる と考えて良いのでしょうか? あるいは、C#は、もともとそこまでは大規模なプログラム向けの言語ではないのでしょうか? そんで、分割の時のことなんですが DllImportで 関数ポインタぽいものを作る時に (意味的に、C・C++でいう)ポインタを引数にとるって事が通常考えられるじゃないですか。 その時なんですけど using System; using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { public partial class Form1 : System.Windows.Forms.Form { [DllImport( "kernel32.dll", CallingConvention = CallingConvention.StdCall )] extern static short QueryPerformanceCounter(ref long x); [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)] extern static short QueryPerformanceFrequency(ref long x); public Form1(){ InitializeComponent(); long cnt = 0, frq = 0; //(1) QueryPerformanceCounter(ref cnt); QueryPerformanceFrequency(ref frq); ・ ・ ・ どうやらこういう風に (1)のところで初期化がいると思うんですよね。 で、あきらかにこれ内部で書きかえられることを想定してるんだから 初期化なしでやりたいんですが 初期化なしでやる場合は outに変える必要があると聞きました。 [DllImport( "kernel32.dll", CallingConvention = CallingConvention.StdCall )] extern static short QueryPerformanceCounter(out long x); [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)] extern static short QueryPerformanceFrequency(out long x); ・ ・ ・ long cnt, frq; QueryPerformanceCounter(out cnt); QueryPerformanceFrequency(out frq); でもこの場合って、実際には中身は書き変えられないかもしれないですよね? その辺はDllImportの場合(自分のアセンブリ内のことしか)関知しないってことでしょうか? それから ・C++などでいうconst(C#ではメンバに付けるreadonly的)なローカル変数 ・同じく、constあるいはreadonly的な、関数への参照渡し(ref) といったものは言語仕様上ない、のでしょうか?

  • C#についての質問です

    Microsoft Visual C# 2010 Express をつかって using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Console { class Program { static void Main(string[] args) { Console.WriteLine("皆様、はじめまして"); } } } と入力して.csで保存したのですが、コマンドプロンプトで 'csc' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。 とでてコンパイルできません。対応を教えてください。

  • C#でウィンドウのアイコン取得する方法

    タスクマネージャのアプリケーションタブに 起動しているアプリケーション名とアイコンが一覧で表示されている部分のように 小さいアイコンを取得したいんですがなかなかうまくいきません。 ファイルに紐付くアイコンと解釈していただいても構いません。 とりあえず、下記のWin32 APIの処理を利用してみましたが SHGetFileInfoだけしかうまくいきませんでした。 しかし、SHGetFileInfoも、アイコンは取得できますがこれはファイルに紐付くアイコンではなく 実行体(EXE)に紐付くアイコンで表示されてしまいました。 開いているウィンドウ情報からだと実行プロセスのEXEのパスしか分からないからです。 ★質問★: ファイルに紐付く小さいアイコンの取得方法を教えてください!できればサンプルソース込みだと助かります。 #region 小さいアイコンを取得するためのWin32 API(ファイルパスから) // SHGetFileInfo関数 [DllImport("shell32.dll")] private static extern IntPtr SHGetFileInfo( string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags); // SHGetFileInfo関数で使用するフラグ private const uint SHGFI_ICON = 0x100; // アイコン・リソースの取得 private const uint SHGFI_LARGEICON = 0x0; // 大きいアイコン private const uint SHGFI_SMALLICON = 0x1; // 小さいアイコン private const uint SHGFI_TYPENAME = 0x400;//ファイルの種類 // SHGetFileInfo関数で使用する構造体 private struct SHFILEINFO { public IntPtr hIcon; public IntPtr iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; #endregion #region 小さいアイコンを取得するためのWin32 API(ウィンドウハンドルからその1) [DllImport("user32.dll", EntryPoint = "GetClassLong")] public static extern IntPtr GetClassLongPtr32(IntPtr hWnd, int nIndex); [DllImport("user32.dll", EntryPoint = "GetClassLongPtr")] public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex); const int GCL_HICON = (-14); const int GCL_HICONSM = (-34); #endregion #region 小さいアイコンを取得するためのWin32 API(ウィンドウハンドルからその2) [DllImport("User32.dll", EntryPoint = "SendMessage")] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); public const int WM_GETICON = 0x7F; public const int WM_SETICON = 0x80; public const int ICON_SMALL = 0; public const int ICON_BIG = 1; #endregion

  • C#からC言語で作成したDLLに文字列の配列の受け渡しをする方法を教えて下さい

    初めまして、プログラミング自体経験が初心者なので根本的なところで間違っているかもしれませんがご指摘いただければと思いまして投稿します。 C#のプログラムからC言語で書かれたDLLを使いたいのですが、いくつか分からないことがあります。1つは文字列の配列の受け渡し方法、もう1つはその配列要素の文字列がマルチバイト文字である場合の方法です。 C#側 using System; using System.Runtime.InteropServices; public class MainClass { [DllImport("Cmdll.dll")] public static extern void SampleMethod([In, Out] string[] s, int x); static void Main() {     string[] str1 = new string[2] {"月曜日", "火曜日"};     SampleMethod(str1, n);     for (int i = 0; i < n; i++)       Console.WriteLine("str1[{0}] = {1}", i, str1[i]);   } } C言語側 void __declspec(dllexport) SampleMethod(char *str[], int n) {   int i;   for (i = 0; i < n; i++)     strcat(str[i], "ですね"); } なお、私用する文字を1バイト文字にすると動作しました。 DllImportの使い方も付け焼刃なので使い方が間違っていたらご指摘願えますでしょうか。よろしくお願いいたします。環境はVisual Studio 2008です。

  • C# タスクバーを隠したフォーム固定の方法

    前略 ・C#の初心者です。 ・先日このMSN相談箱でtsukasa-12rさんからタスクバーを非表示する下記のプログラムをおしえていだきました。 このプログラムでウィンドウフォームを固定しようとして this.FormBorderStyle = FormBorderStyle.FixedSingle; のコードを1行だけ追加しましたがウィンドウフォームを固定できませんでした。  タスクバーを隠して かつウィンドウフォームを固定したいのですが tsukasa-12rさん以外の方でもかまいませんのでどなたか教えてください。  以上、よろしくお願いします //----------------------------------- using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, IntPtr lpWindowName); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); private const int SW_HIDE = 0; private const int SW_NORMAL = 1; [StructLayout(LayoutKind.Sequential)] struct APPBARDATA { public int cbSize; public IntPtr hwnd; public uint uCallbackMessage; public uint uEdge; public Rectangle rc; public int lParam; }; private const int ABM_SETSTATE = 10; private const int ABS_AUTOHIDE = 1; private const int ABS_ALWAYSONTOP = 2; [DllImport("shell32.dll")] static extern int SHAppBarMessage(int msg, ref APPBARDATA pbd ); public Form1() { InitializeComponent(); // 「タスクバーを自動的に隠す」 APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.lParam = ABS_AUTOHIDE; SHAppBarMessage(ABM_SETSTATE, ref abd); // タスクバーを非表示 ShowWindow(FindWindow("Shell_TrayWnd", IntPtr.Zero), SW_HIDE); // コントロールボックスを非表示 this.ControlBox = false; // 最大表示 this.WindowState = FormWindowState.Maximized; this.FormBorderStyle = FormBorderStyle.FixedSingle;// ← ウィンドウサイズを固定しようとして追加 → 固定できず } private void button1_Click(object sender, EventArgs e) { // タスクバーを常に表示 APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.lParam = ABS_ALWAYSONTOP; SHAppBarMessage(ABM_SETSTATE, ref abd); // タスクバーを表示 ShowWindow(FindWindow("Shell_TrayWnd", IntPtr.Zero), SW_NORMAL); // フォームを閉じる this.Close(); } } }

  • 【C#】FindWindowExの使い方を教えてください

    はじめまして Visual Studio 2005を使用しています。 C#.NETは、いじり初めて1週間の超初心者です。 C#.NETでのFindWindowExの使い方を教えてください。 まずはじめに、vb.netで作ったアプリAの"Form1"があり、その中にテキストボックス"TextBox1"があります。 "TextBox1"のテキスト(キャプション?)には同じく"TextBox1"と入力されています。 そこで、C#側のアプリBでVBのアプリAの"Form1"のハンドルをFindWindowで取得します。 ここまでは出来ました。 次に、FindWindowExを使って"TextBox1"のハンドルを取得したいのですが、どうしてもうまく取得できません(0が返ってきます) 以下、C#のソースです。 (textBox1のMultilineはTrueです) ================================================================== using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsApplication1 { public partial class Form1 : Form { [DllImport("user32.dll")] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] static extern IntPtr FindWindowEx(IntPtr hWnd, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); public IntPtr hWnd = (IntPtr)0; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { IntPtr hWnd; IntPtr hWndTest; string sClassName = null; string sWindowText = "AppA"; // アプリAのウインドウハンドルを取得 hWnd = FindWindow(sClassName, sWindowText); textBox1.Text = "ウインドウのハンドル " + hWnd + "\r\n"; // アプリAのウインドウ内のTextBox1のハンドルを取得 hWndTest = hWnd; sClassName = null; sWindowText = "TextBox1"; hWnd = FindWindowEx(hWndTest, IntPtr.Zero, sClassName, sWindowText); textBox1.Text += "テキストボックスのハンドル " + hWnd; } } } ================================================================== Spy++で覗くとテキストボックスにもハンドルが割り与えられているので取得できるはずだと思っているのですが、どうしてもいまくいきません。 どうか、よろしくご享受願います。 ちなみに、アプリAのテキストボックスのクラス名が”WindowsForms10.EDIT.app.0.378734a”となっているのですが、これはどの環境でビルド(コンパイル)しても不変なのでしょうか? 不変だとしたら、クラス名を使えば悩まずに取得できると思うのですが・・・(実験済み)

  • C# wavファイルの再生について

    C#に関しての質問なのでこちらでいいのかわからないのですが、タイトル通りwavファイルの再生についてです。 環境は .NET2003 です。 現在、学校の卒業制作としてC#でゲームの開発を行っているのですが、音楽ファイルの再生の仕方で困っています。 検索してみたところ、playsoundを使用したループ再生には非同期とループを指定すればいい、とありましたが うまく動きませんでした。 そこでThreadを使用しsleepを使うことで擬似的にループ再生をさせているのですが、それだと都合の悪いことが多く別の方法を探しています。 お力になっていただける方がいれば、宜しくお願いします。 ↓は現在のソースから抜き出したものです。 [DllImport("winmm.dll")] private static extern bool PlaySound(string pszSound, int hmod, uint fdwSound); static void Main(){    Thread t1 = new Thread(new ThreadStart(play)); t1.Start(); Thread.Sleep(1000000000); } public static void play(){ PlaySound("daichi.wav", 0, 0x00001 | 0x00008 ); }

専門家に質問してみよう