旧世代のプログラムの保守をおこなっていると遭遇するINIファイル。
当時は初期値を格納したり、設定を格納したりスタンダードな存在でしたが、すっかり鳴りを潜めました。(Microsoftも非推奨ですしね)
そんなINIファイルを読み出すためにWin32APIのGetPrivateProfileStringを利用することが多いと思うのですが、すっかりはまってしまいました。
pinvokeにも記載がある DllImport を次の通り記述しています。
[DllImport("kernel32.dll", CharSet=CharSet.Unicode)] static extern uint GetPrivateProfileString( string lpAppName, // 取得するブロック string lpKeyName, // 取得するキー string lpDefault, // 利用しないのでEmpty StringBuilder lpReturnedString, // バッファ uint nSize, // バッファサイズ string lpFileName); // INIファイル名
実際の呼び出しコードは
public static bool GetIniFile(string fname, string sec, string key, ref string dt) { StringBuilder sb = new StringBuilder(); uint p = GetPrivateProfileString(sec, key, string.Empty, sb, (uint)1024, fname); dt = sb.ToString(); return p == 0 ? false : true; }
としていたのですが、4回目の呼び出しでFatalErrorが出てしまいました。
何度I/Fを見直してもおかしいところはない(と思っていました)のですが、ダメもとでバッファサイズを指定することにしました。
public static bool GetIniFile(string fname, string sec, string key, ref string dt) { StringBuilder sb = new StringBuilder(1024); uint p = GetPrivateProfileString(sec, key, string.Empty, sb, (uint)sb.Capacity, fname); dt = sb.ToString(); return p == 0 ? false : true; }
このコードでエラーがでなくなりました。
当たり前のお話ですが、バッファサイズは正しく渡しましょう…
C# CharSet.Unicode DllImport new StringBuilder public static bool GetIniFile ref string dt return p sb.ToString static extern uint GetPrivateProfileString string fname string key string lpAppName string lpDefault string lpFileName string lpKeyName string sec string.Empty StringBuilder lpReturnedString StringBuilder sb uint nSize uint p バッファサイズ