簡體   English   中英

存儲.NET應用程序的用戶設置的最佳方法是什么?

[英]What is the best way to store user settings for a .NET application?

我有一個.NET 2.0 Windows窗體應用程序。 商店用戶設置的最佳位置在哪里(考慮Windows指南)?

有人指向Application.LocalUserAppDataPath 但是,這會創建一個文件夾結構,如:

C:\\ Documents and Settings \\ user_name \\ Local Settings \\ Application Data \\ company_name \\ product_name \\ product_version \\

如果我發布我的應用程序的版本1並在那里存儲XML文件,然后發布版本2,那將更改為另一個文件夾,對吧? 無論應用程序版本如何,我都希望每個用戶都有一個文件夾來存儲設置。

我喜歡使用內置的應用程序設置 然后,如果您希望在設計時或運行時使用,則內置支持使用設置設計器:

// read setting
string setting1 = (string)Settings.Default["MySetting1"];
// save setting
Settings.Default["MySetting2"] = "My Setting Value";

// you can force a save with
Properties.Settings.Default.Save();

它會將設置存儲在您描述的類似文件夾結構中(使用路徑中的版本)。 但是,通過簡單的電話:

Properties.Settings.Default.Upgrade(); 

該應用程序將拉入所有以前的版本設置以保存。

.NET應用程序具有易於使用的內置設置機制。 在我看來,它的問題在於它將這些設置存儲到一個相當模糊的目錄中,最終用戶將無法找到它。 此外,只需從調試版本切換到發布版本,即可更改此目錄的位置,這意味着保存在一個配置中的任何設置都會丟失。

出於這些原因和其他原因,我想出了自己的Windows窗體設置代碼 它不像.NET附帶的那樣光滑,但它更靈活,我一直都在使用它。

或者將您的設置寫入xml文件並使用獨立存儲保存 根據您使用的商店,它將其保存在Application Data文件夾中。 您還可以選擇啟用漫游的商店,這意味着當用戶登錄其他計算機時,設置隨之移動。

過去一種對我有用的方法是創建一個設置類,並使用XML序列化將其寫入文件系統。 您可以通過創建一組設置對象並對其進行序列化來擴展此概念。 您可以在一個位置為所有用戶設置所有設置,而無需擔心管理文件系統。

在任何人給我任何部分重新發明輪子之前,讓我說幾件事。 首先,序列化和寫入文件只需幾行代碼。 其次,如果您有一個包含設置的對象,則在加載應用程序時不必多次調用appSettings對象。 最后,添加代表應用程序狀態的項目非常容易,從而允許您在下次加載應用程序時恢復長時間運行的任務。

我嘗試了一些方法將我的設置存儲到簡單的文本文件,我找到了最好的方法:

存儲在應用程序文件夾中的文件,用法, settings.txt :(內部設置文件批准的評論,嘗試//評論)

//獲取設置值

Settings.Get("name", "Ivan");

//設置設置值

Settings.Set("name", "John");

使用:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

//你也可以用section name存儲,只使用add name section Set(section_name,name,value)和Get(section_name,name,value)

public static class Settings
{
    private static string SECTION =  typeof(Settings).Namespace;//"SETTINGS";
    private static string settingsPath = Application.StartupPath.ToString() + "\\settings.txt";
    [DllImport("kernel32")]
    private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
    [DllImport("kernel32")]
    private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
    public static String GetString(String name)
    {
        StringBuilder temp = new StringBuilder(255);
        int i = GetPrivateProfileString(SECTION,name,"",temp,255,settingsPath);
        return temp.ToString();
    }
    public static String Get(String name, String defVal)
    {
        return Get(SECTION,name,defVal);
    }
    public static String Get(string _SECTION, String name, String defVal)
    {
        StringBuilder temp = new StringBuilder(255);
        int i = GetPrivateProfileString(_SECTION, name, "", temp, 255, settingsPath);
        return temp.ToString();
    }
    public static Boolean Get(String name, Boolean defVal)
    {
        return Get(SECTION, name, defVal);
    }
    public static Boolean Get(string _SECTION, String name, Boolean defVal)
    {
        StringBuilder temp = new StringBuilder(255);
        int i = GetPrivateProfileString(_SECTION,name,"",temp,255,settingsPath);
        bool retval=false;
        if (bool.TryParse(temp.ToString(),out retval))
        {
            return retval;
        } else
        {
            return retval;
        }
    }
    public static int Get(String name, int defVal)
    {
        return Get(SECTION, name, defVal);
    }
    public static int Get(string _SECTION, String name, int defVal)
    {
        StringBuilder temp = new StringBuilder(255);
        int i = GetPrivateProfileString(SECTION,name,"",temp,255,settingsPath);
        int retval=0;
        if (int.TryParse(temp.ToString(),out retval))
        {
            return retval;
        } else
        {
            return retval;
        }
    }
    public static void Set(String name, String val)
    {
        Set(SECTION, name,val);
    }
    public static void Set(string _SECTION, String name, String val)
    {
        WritePrivateProfileString(_SECTION, name, val, settingsPath);
    }
    public static void Set(String name, Boolean val)
    {
        Set(SECTION, name, val);
    }
    public static void Set(string _SECTION, String name, Boolean val)
    {
        WritePrivateProfileString(_SECTION, name, val.ToString(), settingsPath);
    }
    public static void Set(String name, int val)
    {
        Set(SECTION, name, val);
    }
    public static void Set(string _SECTION,String name, int val)
    {
        WritePrivateProfileString(SECTION, name, val.ToString(), settingsPath);
    }
}

設置是標准鍵值對(字符串 - 字符串)。 如果有幫助的話,我可以將它們包裝在XML文件中。

我寧願使用文件系統而不是注冊表。 它似乎更容易維護。 在支持方案中,如果用戶需要手動打開/更改設置,那么如果它在文件系統中會更容易。

我會在你發布的文件夾列表中刪除產品版本。 更新發布后,您不希望重置設置。

由於調試/占用因素,我實際上正在遠離用戶設置的注冊表。 我目前只在注冊表中存儲了一些基本設置(窗口大小,位置,數據文件的版本),如果更新變壞或用戶丟失了第二台顯示器,那么我遇到了更多問題該申請正在開放。 他們中的一些人精明到足以理解注冊,但其余的他們必須重新安裝,這很快,但我認為他們抱怨了一下。 使用基於文件的版本,我所要做的就是讓它們在記事本中打開一個XML文件並進行快速調整。

另外,我希望讓我的應用程序可以從USB閃存驅動器上運行,並且將設置綁定到文件中似乎對該過程更友好。 我確信我可以做一些代碼來檢查/清理注冊表,但我想我們大多數人已經厭倦了現在似乎吃掉我們機器的注冊表混亂。

我知道這有一些安全性權衡,但我正在排序的數據都沒有對這個原因至關重要,而且由於應用程序的大小,我沒有遇到任何性能問題。

隔離存儲主要用於使用ClickOnce分發的應用程序 ,並在安全沙箱中運行。 基本路徑是由您決定的,您將無法在代碼中推斷它。 路徑將類似於“\\ LocalSettings \\ ApplicationData \\ IsolatedStorage \\ ejwnwe.302 \\ kfiwemqi.owx \\ url.asdaiojwejoieajae ....”,並不是那么友好。 您的存儲空間也有限。

Ryan Farley說得對

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM