625

私が実現したいことは非常に単純です。情報の読み取りにパスを使用する Windows フォーム (.NET 3.5) アプリケーションがあります。このパスは、私が提供するオプション フォームを使用して、ユーザーが変更できます。

ここで、後で使用するためにパス値をファイルに保存したいと考えています。これは、このファイルに保存される多くの設定の 1 つです。このファイルは、アプリケーション フォルダーに直接配置されます。

次の 3 つのオプションがあることを理解しています。

  • ConfigurationSettings ファイル (appname.exe.config)
  • レジストリ
  • カスタム XML ファイル

.NET 構成ファイルに値を保存することは想定されていないことを読みました。レジストリに関しては、できるだけ離れたいと思います。

これは、カスタム XML ファイルを使用して構成設定を保存する必要があるということですか?

もしそうなら、そのコード例(C#)を見たいです。

この件に関する他の議論を見たことがありますが、まだはっきりしていません。

4

14 に答える 14

635

Visual Studio を使用している場合、永続化可能な設定を取得するのは非常に簡単です。ソリューション エクスプローラーでプロジェクトを右クリックし、[プロパティ] を選択します。[設定] タブを選択し、設定が存在しない場合はハイパーリンクをクリックします。

[設定] タブを使用して、アプリケーション設定を作成します。Visual Studio は、ApplicationSettingsBaseから継承さ れたシングルトン クラスを含むファイルSettings.settingsを作成します。コードからこのクラスにアクセスして、アプリケーション設定を読み書きできます。Settings.Designer.settingsSettings

Properties.Settings.Default["SomeProperty"] = "Some Value";
Properties.Settings.Default.Save(); // Saves settings in application configuration file

この手法は、コンソール、Windows フォーム、およびその他のプロジェクト タイプの両方に適用できます。

設定のスコーププロパティを設定する必要があることに注意してください。アプリケーション スコープを選択すると、Settings.Default.<your property> は読み取り専用になります。

リファレンス:方法: C# を使用して実行時にユーザー設定を記述する - Microsoft Docs

于 2009-01-17T12:18:01.227 に答える
101

実行可能ファイルと同じディレクトリ内のファイルに保存することを計画している場合は、JSON形式を使用する優れたソリューションを次に示します。

using System;
using System.IO;
using System.Web.Script.Serialization;

namespace MiscConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            MySettings settings = MySettings.Load();
            Console.WriteLine("Current value of 'myInteger': " + settings.myInteger);
            Console.WriteLine("Incrementing 'myInteger'...");
            settings.myInteger++;
            Console.WriteLine("Saving settings...");
            settings.Save();
            Console.WriteLine("Done.");
            Console.ReadKey();
        }

        class MySettings : AppSettings<MySettings>
        {
            public string myString = "Hello World";
            public int myInteger = 1;
        }
    }

    public class AppSettings<T> where T : new()
    {
        private const string DEFAULT_FILENAME = "settings.json";

        public void Save(string fileName = DEFAULT_FILENAME)
        {
            File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(this));
        }

        public static void Save(T pSettings, string fileName = DEFAULT_FILENAME)
        {
            File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(pSettings));
        }

        public static T Load(string fileName = DEFAULT_FILENAME)
        {
            T t = new T();
            if(File.Exists(fileName))
                t = (new JavaScriptSerializer()).Deserialize<T>(File.ReadAllText(fileName));
            return t;
        }
    }
}
于 2011-06-30T22:16:52.993 に答える
69

レジストリはダメです。アプリケーションを使用するユーザーが、レジストリに書き込む十分な権限を持っているかどうかはわかりません。

このapp.configファイルを使用して、アプリケーション レベルの設定を保存できます (アプリケーションを使用する各ユーザーに対して同じです)。

ユーザー固有の設定を XML ファイルに保存し、それを分離ストレージまたはSpecialFolder.ApplicationDataディレクトリに保存します。

次に、.NET 2.0 以降では、値をapp.configファイルに保存することができます。

于 2009-01-17T11:33:57.073 に答える
20

このクラスは、 app.configファイルApplicationSettingsへの設定の保存をサポートしていません。これは設計によるものです。適切に保護されたユーザー アカウント (Vista UAC を考えてください) で実行されるアプリケーションには、プログラムのインストール フォルダーへの書き込みアクセス権がありません。

ConfigurationManagerクラスでシステムと戦うことができます。ただし、簡単な回避策は、設定デザイナーに移動して、設定のスコープをユーザーに変更することです。それが問題を引き起こす場合 (たとえば、設定がすべてのユーザーに関連する場合)、オプション機能を別のプログラムに配置して、特権昇格のプロンプトを要求できるようにする必要があります。または、設定の使用を控えます。

于 2009-01-17T14:45:56.157 に答える
18

registry/configurationSettings/XML 引数はまだ非常にアクティブなようです。技術が進歩したので、私はそれらをすべて使用しましたが、私のお気に入りは、分離ストレージと組み合わせたThreed のシステムに基づいています。

次のサンプルでは、​​プロパティという名前のオブジェクトを分離ストレージ内のファイルに格納できます。そのような:

AppSettings.Save(myobject, "Prop1,Prop2", "myFile.jsn");

プロパティは、次を使用して回復できます。

AppSettings.Load(myobject, "myFile.jsn");

これは単なるサンプルであり、ベスト プラクティスを示唆するものではありません。

internal static class AppSettings
{
    internal static void Save(object src, string targ, string fileName)
    {
        Dictionary<string, object> items = new Dictionary<string, object>();
        Type type = src.GetType();

        string[] paramList = targ.Split(new char[] { ',' });
        foreach (string paramName in paramList)
            items.Add(paramName, type.GetProperty(paramName.Trim()).GetValue(src, null));

        try
        {
            // GetUserStoreForApplication doesn't work - can't identify.
            // application unless published by ClickOnce or Silverlight
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Create, storage))
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write((new JavaScriptSerializer()).Serialize(items));
            }

        }
        catch (Exception) { }   // If fails - just don't use preferences
    }

    internal static void Load(object tar, string fileName)
    {
        Dictionary<string, object> items = new Dictionary<string, object>();
        Type type = tar.GetType();

        try
        {
            // GetUserStoreForApplication doesn't work - can't identify
            // application unless published by ClickOnce or Silverlight
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Open, storage))
            using (StreamReader reader = new StreamReader(stream))
            {
                items = (new JavaScriptSerializer()).Deserialize<Dictionary<string, object>>(reader.ReadToEnd());
            }
        }
        catch (Exception) { return; }   // If fails - just don't use preferences.

        foreach (KeyValuePair<string, object> obj in items)
        {
            try
            {
                tar.GetType().GetProperty(obj.Key).SetValue(tar, obj.Value, null);
            }
            catch (Exception) { }
        }
    }
}
于 2011-10-11T15:24:09.690 に答える
16

簡単な方法は、構成データ オブジェクトを使用し、それをアプリケーションの名前で XML ファイルとしてローカル フォルダーに保存し、起動時にそれを読み戻すことです。

フォームの位置とサイズを格納する例を次に示します。

構成データオブジェクトは厳密に型指定されており、使いやすいです。

[Serializable()]
public class CConfigDO
{
    private System.Drawing.Point m_oStartPos;
    private System.Drawing.Size m_oStartSize;

    public System.Drawing.Point StartPos
    {
        get { return m_oStartPos; }
        set { m_oStartPos = value; }
    }

    public System.Drawing.Size StartSize
    {
        get { return m_oStartSize; }
        set { m_oStartSize = value; }
    }
}

保存および読み込み用のマネージャー クラス:

public class CConfigMng
{
    private string m_sConfigFileName = System.IO.Path.GetFileNameWithoutExtension(System.Windows.Forms.Application.ExecutablePath) + ".xml";
    private CConfigDO m_oConfig = new CConfigDO();

    public CConfigDO Config
    {
        get { return m_oConfig; }
        set { m_oConfig = value; }
    }

    // Load configuration file
    public void LoadConfig()
    {
        if (System.IO.File.Exists(m_sConfigFileName))
        {
            System.IO.StreamReader srReader = System.IO.File.OpenText(m_sConfigFileName);
            Type tType = m_oConfig.GetType();
            System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType);
            object oData = xsSerializer.Deserialize(srReader);
            m_oConfig = (CConfigDO)oData;
            srReader.Close();
        }
    }

    // Save configuration file
    public void SaveConfig()
    {
        System.IO.StreamWriter swWriter = System.IO.File.CreateText(m_sConfigFileName);
        Type tType = m_oConfig.GetType();
        if (tType.IsSerializable)
        {
            System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType);
            xsSerializer.Serialize(swWriter, m_oConfig);
            swWriter.Close();
        }
    }
}

インスタンスを作成し、フォームの load イベントと close イベントで使用できるようになりました。

    private CConfigMng oConfigMng = new CConfigMng();

    private void Form1_Load(object sender, EventArgs e)
    {
        // Load configuration
        oConfigMng.LoadConfig();
        if (oConfigMng.Config.StartPos.X != 0 || oConfigMng.Config.StartPos.Y != 0)
        {
            Location = oConfigMng.Config.StartPos;
            Size = oConfigMng.Config.StartSize;
        }
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        // Save configuration
        oConfigMng.Config.StartPos = Location;
        oConfigMng.Config.StartSize = Size;
        oConfigMng.SaveConfig();
    }

また、生成された XML ファイルも読み取り可能です。

<?xml version="1.0" encoding="utf-8"?>
<CConfigDO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <StartPos>
    <X>70</X>
    <Y>278</Y>
  </StartPos>
  <StartSize>
    <Width>253</Width>
    <Height>229</Height>
  </StartSize>
</CConfigDO>
于 2015-11-25T13:18:02.177 に答える
7

web.configorを使用するという提案された解決策は好きではありませんapp.config。独自の XML を読んでみてください。XML 設定ファイル – もう web.configを見てください。

于 2009-09-09T21:49:24.477 に答える
3

私が知る限り、.NET は組み込みのアプリケーション設定機能を使用して永続的な設定をサポートしています。

Windows フォームのアプリケーション設定機能を使用すると、クライアント コンピューターでカスタム アプリケーションとユーザー設定を簡単に作成、保存、および維持できます。Windows フォーム アプリケーション設定を使用すると、データベース接続文字列などのアプリケーション データだけでなく、ユーザー アプリケーション設定などのユーザー固有のデータも格納できます。Visual Studio またはカスタム マネージ コードを使用して、新しい設定を作成し、それらをディスクから読み取ったりディスクに書き込んだり、フォームのプロパティにバインドしたり、ロードおよび保存する前に設定データを検証したりできます。- http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx

于 2009-01-17T11:34:10.257 に答える
2

従来の web.config または app.config ファイルに保持されている設定を削除したい場合があります。設定エントリの展開と分離されたデータ設計をより細かく制御したい。または、要件は、実行時に新しいエントリを追加できるようにすることです。

2 つの良いオプションを想像できます。

  • 強く型付けされたバージョンと
  • オブジェクト指向版。

厳密に型指定されたバージョンの利点は、厳密に型指定された設定の名前と値です。名前やデータ型が混在するリスクはありません。欠点は、より多くの設定をコーディングする必要があり、実行時に追加できないことです。

オブジェクト指向バージョンの利点は、実行時に新しい設定を追加できることです。ただし、厳密に型指定された名前と値はありません。文字列識別子には注意が必要です。値を取得するときに、以前に保存されたデータ型を知っている必要があります。

両方の完全に機能する実装のコードは、こちらで確認できます。

于 2013-12-23T17:41:36.827 に答える
1
public static class SettingsExtensions
{
    public static bool TryGetValue<T>(this Settings settings, string key, out T value)
    {
        if (settings.Properties[key] != null)
        {
            value = (T) settings[key];
            return true;
        }

        value = default(T);
        return false;
    }

    public static bool ContainsKey(this Settings settings, string key)
    {
        return settings.Properties[key] != null;
    }

    public static void SetValue<T>(this Settings settings, string key, T value)
    {
        if (settings.Properties[key] == null)
        {
            var p = new SettingsProperty(key)
            {
                PropertyType = typeof(T),
                Provider = settings.Providers["LocalFileSettingsProvider"],
                SerializeAs = SettingsSerializeAs.Xml
            };
            p.Attributes.Add(typeof(UserScopedSettingAttribute), new UserScopedSettingAttribute());
            var v = new SettingsPropertyValue(p);
            settings.Properties.Add(p);
            settings.Reload();
        }
        settings[key] = value;
        settings.Save();
    }
}
于 2016-07-27T16:44:11.720 に答える