.netの異なるアセンブリバージョン間でuser.config設定をどのように維持しますか?


146

基本的に問題は、アセンブリのバージョンが変更される(つまり、ユーザーがアプリケーションの新しいバージョンをインストールする)たびに、すべての設定がデフォルトにリセットされることです(正確には、新しいバージョンのフォルダーに新しいuser.configファイルが作成されます)名前としての番号)

バージョンのアップグレード時に同じ設定を維持するにはどうすればよいですか。iniファイルまたはレジストリの使用は推奨されないようです。

Clickonceを使用した場合、これを処理できるように見えたので、それを実行できるはずですが、方法はわかりません。



いいえ、それはデフォルトでファイルをバージョン管理にチェックインしない(または私が収集した)ことを指します。これは、エンドユーザーの(Windows)ユーザー固有の設定に関するものです
Davy8


可能な解決策を次のスレッドに投稿しました:stackoverflow.com/a/47921377/3223783お役に立てれば幸いです。
dontbyteme 2017

私はこのスレッドで可能な解決策を投稿しました。お役に立てば幸いです。
dontbyteme 2017

回答:


236

ApplicationSettingsBaseには、以前のバージョンからすべての設定を移行するUpgradeというメソッドがあります。

アプリケーションの新しいバージョンを公開するたびにマージを実行するために、デフォルトでtrueに設定されているブールフラグを設定ファイルで定義できます。UpgradeRequiredなどの名前を付けます。

次に、アプリケーションの起動時にフラグが設定されているかどうかを確認し、設定されている場合はUpgradeメソッドを呼び出して、フラグをfalseに設定し、構成を保存します。

if (Settings.Default.UpgradeRequired)
{
    Settings.Default.Upgrade();
    Settings.Default.UpgradeRequired = false;
    Settings.Default.Save();
}

MSDNでアップグレード方法の詳細を読んでください。GetPreviousVersionはあなたには、いくつかのカスタムマージを行う必要がある場合も一見の価値があるかもしれません。


2
小さな質問ですが、何が新しいバージョンを構成していますか?4つの部品番号のどの部分ですか?ClickOnceを使用していますが、別の動物ですか?
パラディンが屈折した2013

4
UpgradeRequiredにはどのような設定をする必要がありますか?appSettingsuserSettingsまたはapplicationSettings?Settings.Settingsのユーザー設定として、初めてfalseに変更されると、再びtrueになることはありません。新しいバージョンでは、UpgradeRequiredがTrueにリセットされません。
dialex 2015

4
@dialexユーザー設定である必要があります。タイプアプリケーションの設定は読み取り専用です。設定はバージョン固有のパスに保存されるため、新しいバージョン番号では設定がリセットされます。
Leonard Thieu、2015年

4
自分の質問に答えたと思います。以前のバージョンの設定ファイルが存在する場合、アプリが起動するたびに、その値が最新バージョンにコピーされます。
ヒュージェフナー2017年

1
これが単なるデフォルトの動作ではないことに少し驚いています。起動時にアプリケーションの設定がnullであり、以前の一連の設定が見つかった場合は、それらをロードします。
SteveCinq

3

私はそれがしばらくの間だったことを知っています... winformsアプリでは、My.Settings.Upgrade()ロードする前に呼び出します。これにより、現在のバージョンでも前のバージョンでも、最新の設定が取得されます。


2

変更/削除された設定の移行で他の誰かが苦労している場合の私の調査です。GetPreviousVersion()アプリケーションの新しいバージョンで設定の名前を変更または削除した場合、基本的な問題は機能しません。したがって、Settingsクラス内の設定を維持する必要がありますが、いくつかの属性/アーティファクトを追加して、他の場所のコードで誤って使用しないようにし、陳腐化させます。VB.NETでは、廃止されたサンプル設定は次のようになります(簡単にC#に変換できます)。

<UserScopedSetting(),
DebuggerNonUserCode(),
DefaultSettingValue(""),
Obsolete("Do not use this property for any purpose. Use YOUR_NEW_SETTING_NAME instead."),
NoSettingsVersionUpgrade()>
Public Property OldSettingName() As String
  Get
    Throw New NotSupportedException("This property is obsolete")
  End Get
  Set
    Throw New NotSupportedException("This property is obsolete")
  End Set
End Property

このプロパティは、アプリケーションの設定と同じ名前空間/クラスに追加してください。VB.NETでは、このクラスに名前が付けられMySettingsMy名前空間で使用できます。部分的なクラス機能を使用して、古い設定が現在の設定と混同しないようにすることができます。

この問題に関する優れた記事を投稿してくれたjsharrisonの功績です。詳細については、こちらをご覧ください。


1

ここに示すソリューションのバリエーションは、アップグレードロジックを、設定クラスから派生できる抽象クラスにカプセル化したものです。

提案されている一部のソリューションでは、DefaultSettingsValue属性を使用して、以前の設定が読み込まれなかった時期を示す値を指定しています。私の好みは、デフォルト値がこれを示すタイプを使用することです。おまけとして、DateTime?役立つデバッグ情報です。

public abstract class UserSettingsBase : ApplicationSettingsBase
{
    public UserSettingsBase() : base()
    {
        // Accessing a property attempts to load the settings for this assembly version
        // If LastSaved has no value (default) an upgrade might be needed
        if (LastSaved == null)
        {
            Upgrade();
        }
    }

    [UserScopedSetting]
    public DateTime? LastSaved
    {
        get { return (DateTime?)this[nameof(LastSaved)]; }
        private set { this[nameof(LastSaved)] = value; }
    }

    public override void Save()
    {
        LastSaved = DateTime.Now;
        base.Save();
    }
}

UserSettingsBaseから派生:

public class MySettings : UserSettingsBase
{
    [UserScopedSetting]
    public string SomeSetting
    {
        get { return (string)this[nameof(SomeSetting)]; }
        set { this[nameof(SomeSetting)] = value; }
    }

    public MySettings() : base() { }
}

そしてそれを使う:

// Existing settings are loaded and upgraded if needed
MySettings settings = new MySettings();
...
settings.SomeSetting = "SomeValue";
...
settings.Save();

0

user.settingsへの変更がプログラムで行われる場合、user.customized.settingsなどの別のファイルでuser.settingsへの変更のコピー(だけ)を維持するのはどうですか?

おそらく、user.settingsの変更された設定も維持してロードする必要があります。しかし、このようにして、新しいバージョンのアプリケーションを新しいバージョンのuser.settingsでインストールするときに、変更した設定を新しいuser.settingsにコピーして戻すことを続けるかどうかをユーザーに尋ねることができます。それらを卸売りでインポートするか、より洗練されたものにして、引き続き使用したい設定をユーザーに確認するよう依頼することができます。

編集:新しいuser.settingsが新しいバージョン固有のディレクトリにインストールされる原因となる、アセンブリバージョンについての「より正確な」部分をすばやく読みました。したがって、上記のアイデアはおそらく役に立たないかもしれませんが、思考の糧になるかもしれません。


0

これは私がそれを処理した方法です:

public virtual void LoadSettings(ServiceFileFormBaseSettings settings = null, bool resetSettingsToDefaults = false)
{
    if (settings == null)
            return;

    if (resetSettingsToDefaults)
        settings.Reset();
    else
    {
        settings.Reload();

        if (settings.IsDefault)
            settings.Upgrade();
    }

    this.Size = settings.FormSize;

}

設定クラスでは、IsDefaultプロパティを定義しました。

// SaveSettings always sets this to be FALSE.
// This will have the default value TRUE when first deployed, or immediately after an upgrade.
// When the settings exist, this is false.
//
[UserScopedSettingAttribute()]
[DefaultSettingValueAttribute("true")]
public virtual bool IsDefault
{
    get { return (bool)this["IsDefault"]; }
    set { this["IsDefault"] = value; }
}

SaveSettingsで、IsDefaultをfalseに設定します。

public virtual void SaveSettings(ServiceFileFormBaseSettings settings = null)
{
    if (settings == null) // ignore calls from this base form, if any
        return;

    settings.IsDefault = false;
    settings.FormSize = this.Size;
    settings.Save();
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.