質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

1回答

1273閲覧

INIファイル読み書きの自動化実現

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

1クリップ

投稿2021/10/21 12:32

前提・実現したいこと

業務ソフトウェアをカスタマイズするために、ソフト定義ファイル(INI)を読み書きできるWindows Formアプリを開発しております。

日々、業務ソフトウェアは機能が追加されていて新規項目の読み込む処理、画面に表示する処理、書き込む処理を追加された分繰り返すのは効率が悪いと思い、
読み込み処理(IniFileRWClass)と書き込み処理(WriteIniSetting)を自動化させたいと考えております。

問題 ⇒ 書き込み処理
Activator.CreateInstance(Type)で新規インスタンス生成してが原因でNULになっているまでは突き止めたのですが、そこから値取得までの解決策が見つけれていません。

発生している問題・エラーメッセージ

例外がスローされました: 'System.NullReferenceException' (WindowsFormApp.exe の中)

該当のソースコード

INI

1/** ファイル名 File.ini **/ 2[Version] 3major=1 4release=true 5 6[Info] 7File=AAA.txt

C#

1using System; 2using System.Reflection; 3using System.Runtime.InteropServices; 4using System.Text; 5 6namespace WindowsFormApp 7{ 8 /// <summary> 9 /// 設定保存用クラス 10 /// </summary> 11 [IniFileName("File.ini")] 12 public class SettingClass 13 { 14 public SEC_VERSION version { get; set; } 15 public SEC_INFO info { get; set; } 16 } 17 18 [IniFileSection("Version")] 19 public class SEC_VERSION 20 { 21 [IniFile("major", DefaultValue = "1")] 22 public string Major { get; set; } 23 24 [IniFile("release", DefaultValue = true)] 25 public bool Release { get; set; } 26 } 27 28 [IniFileSection("Info")] 29 public class SEC_INFO 30 { 31 [IniFile("File", DefaultValue = "AAA.txt")] 32 public string File { get; set; } 33 } 34 35 /// <summary> 36 /// INIファイル名属性 37 /// </summary> 38 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] 39 public class IniFileNameAttribute : System.Attribute 40 { 41 public string FileName { get; set; } 42 43 public IniFileNameAttribute(string filename) 44 { 45 FileName = filename; 46 } 47 } 48 49 /// <summary> 50 /// INIファイルに対するセクション属性 51 /// </summary> 52 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] 53 public class IniFileSectionAttribute : Attribute 54 { 55 /// <summary> 56 /// セクション名 57 /// </summary> 58 public string Section { get; set; } 59 60 public IniFileSectionAttribute(string section) 61 { 62 Section = section; 63 } 64 } 65 66 /// <summary> 67 /// INIファイルに対する属性値 68 /// </summary> 69 [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] 70 public class IniFileAttribute : Attribute 71 { 72 /// <summary> 73 /// キー 74 /// </summary> 75 public string Key { get; set; } 76 /// <summary> 77 /// デフォルト値 78 /// </summary> 79 public object DefaultValue { get; set; } 80 81 /// <summary> 82 /// INIに対する連携用属性 83 /// </summary> 84 /// <param name="key">キー</param> 85 public IniFileAttribute(string key) 86 { 87 Key = key; 88 DefaultValue = string.Empty; 89 } 90 } 91 92 /// <summary> 93 /// INIファイル操作系 94 /// </summary> 95 public static class IniFileRWClass 96 { 97 #region INIファイル操作 98 /// <summary> 99 /// INIファイルから文字列の取得 100 /// </summary> 101 /// <param name="lpAppName">アプリケーション名</param> 102 /// <param name="lpKeyName">キー</param> 103 /// <param name="lpDefault">デフォルト値</param> 104 /// <param name="lpReturnedString">戻り値</param> 105 /// <param name="nSize">最大文字数</param> 106 /// <param name="lpFileName">ファイル名</param> 107 /// <returns>読み取りバイト数</returns> 108 [DllImport("KERNEL32.DLL")] 109 public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName); 110 111 /// <summary> 112 /// INIファイルへ文字列の書き込み 113 /// </summary> 114 /// <param name="lpAppName">アプリケーション名</param> 115 /// <param name="lpKeyName">キー</param> 116 /// <param name="lpString">書き込み文字数</param> 117 /// <param name="lpFileName">ファイル名</param> 118 /// <returns></returns> 119 [DllImport("KERNEL32.DLL")] 120 public static extern uint WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName); 121 #endregion 122 123 #region INI設定ファイル操作 124 /// <summary> 125 /// 設定をファイルから取り込む 126 /// </summary> 127 /// <returns></returns> 128 public static SettingClass ReadIniSetting() 129 { 130 /**省略**/ 131 } 132 133 /// <summary> 134 /// 設定をファイルに書き込む 135 /// </summary> 136 /// <param name="data"></param> 137 public static void WriteIniSetting(SettingClass sc) 138 { 139 Console.WriteLine("Call:WriteIniSetting()"); 140 141 Type tSettingClass = sc.GetType(); 142 143 var iniFileNameAttribute = (IniFileNameAttribute)Attribute.GetCustomAttribute(tSettingClass, typeof(IniFileNameAttribute)); 144 if (iniFileNameAttribute == null) return; 145 146 string iniFileName = iniFileNameAttribute.FileName; 147 string dirApplication = System.Windows.Forms.Application.StartupPath; 148 149 iniFileName = System.IO.Path.Combine(dirApplication, iniFileName); 150 151 var pfSettingClass = tSettingClass.GetProperties(); 152 153 foreach (var prSettingClass in pfSettingClass) 154 { 155 Type ptSettingSubClass = prSettingClass.PropertyType; 156 var instSettingSubClass = Activator.CreateInstance(ptSettingSubClass); 157 var proSettingClass = tSettingClass.GetProperty(prSettingClass.Name); 158 159 var iniFileSectionAttribute = (IniFileSectionAttribute)Attribute.GetCustomAttribute(ptSettingSubClass, typeof(IniFileSectionAttribute)); 160 161 if (iniFileSectionAttribute == null) continue; 162 string sectionName = iniFileSectionAttribute.Section; 163 164 var pf = ptSettingSubClass.GetProperties(); 165 166 foreach (var pr in pf) 167 { 168 var iniFileAttribute = (IniFileAttribute)pr.GetCustomAttribute(typeof(IniFileAttribute)); 169 if (iniFileAttribute == null) continue; 170 171 string keyName = iniFileAttribute.Key; 172 173 var p = ptSettingSubClass.GetProperty(pr.Name); 174 175 if (pr.PropertyType == typeof(string)) 176 { 177 // 書き込み処理 ⇒ WritePrivateProfileString(sectionName, keyName, p.GetValue(instSettingSubClass).ToString(), iniFileName); 178 Console.WriteLine($"[{sectionName}] {keyName} = {p.GetValue(instSettingSubClass).ToString()}"); 179 } 180 else if (pr.PropertyType == typeof(Boolean)) 181 { 182 /** 省略 **/ 183 } 184 } 185 } 186 #endregion 187 } 188 } 189}

参考URL

  • C#でINIファイル操作を属性(Attribute)使ってやってみた

https://qiita.com/tanoue2715/items/ba15f181cd4f58dc9a5f

  • PropertyInfo.GetValue メソッド

https://docs.microsoft.com/ja-jp/dotnet/api/system.reflection.propertyinfo.getvalue?view=net-5.0

補足情報(FW/ツールのバージョンなど)

開発環境:Virtual Studio Professional 2019 ver16.11.5
対象フレームワーク:.NET Framework 4.8

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/10/22 00:31

INIファイルの扱いで、なぜこうも複雑でややこしい話になるのか分からない、、、
退会済みユーザー

退会済みユーザー

2021/10/22 01:58 編集

新規開発なら、INIファイルなどやめてXmlSerializer辺りを使えばいいんじゃないでしょうか。オブジェクトのXMLファイルへの保存・復元が簡単に出来ます。INIファイルAPIはShift_JISしか扱えないし、あくまでレガシープログラムとの互換性のために残されているものです。
guest

回答1

0

なんでWriteでCreateInstanceしてるの? (ReadがCreateInstanceするならまだわかる。)
つまりnew SEC_VERSION().Major はnullだから、後段の p.GetValue(instSettingSubClass)がnullを返して、null.ToString()で、ぬるぽになるんでしょう。
object instSettingSubClass = prSettingClass.GetValue(sc);
で、scのメンバを取得する必要があるでしょうね。

個人的にはデフォルト値の設定は [IniFile("major")] public string Major { get; set; } = "1"; とかにして、INIを読んだ結果の中身が空なら放っておけばいいとおもうし、SettingClassも public SEC_VERSION version { get; } = new SEC_VERSION();とかでreadonly propertyの方が話がスッキリするとおもう。

投稿2021/10/21 13:26

matukeso

総合スコア1681

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問