.Net開發的系統安裝或更新時如何避免覆蓋使用者自定義的設定

2023-01-12 18:00:40

我們開發的系統,有時候會包含一些設定資訊,需要使用者在系統安裝後自己去設定,例如我們有一個GPExSettings.xml檔案,內容如下。

<GPExSettings ArcPythonPath="C:\Python27\ArcGIS10.8\python.exe" IsUseArcPython="False" />

正常情況下,使用者安裝了系統,使用過程中,會對系統進行一些設定,即修改了GPExSettings.xml檔案。過段時間,如果系統更新了,無論是解除安裝後再重新安裝,還是直接安裝系統進行更新,都會把GPExSettings.xml替換掉,這樣使用者自定義的設定就不見了。

這樣使用者體驗還是比較差的,每次安裝後,都要重新設定一遍,如果只有一兩個設定項還可以,如果很多的話,使用者會瘋掉的。或則你在說明書上寫上,在安裝新版本之前,把安裝目錄下的某個xml檔案先拷貝出來,安裝後,再拷貝過去,這樣的傻方案,你還別說,剛畢業沒多長時間的時候,我就跟使用者這麼說過。

1、在打包的時候解決

開發桌面軟體,我打包的時候使用Inno Setup Compiler工具,但都使用裡面比較簡單的功能,例如設定系統名稱、版本號、要打包的檔案、桌面圖示、開始選單和解除安裝選單等。

Inno Setup Compiler中主要的內容如下。

[Files]
Source: "D:\2022\01GeoChem_2022\程式碼\打包\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "D:\2022\01GeoChem_2022\程式碼\打包\DEV\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}";IconFilename: "{app}\App.ico"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{app}\unins000.exe"
Name: "{userdesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\App.ico";

【Files】部分設定了要打包那些資料夾或者檔案,[Icons]部分設定了開始選單、解除安裝選單以及桌面圖示。如果你想設定GPExSettings.xml檔案在部署的時候,通過安裝目錄下有同名檔案,可以選擇不覆蓋,這個我在網上查了下,新增上一個命令就可以了。但如果有好幾個這樣的檔案,還是比較麻煩的。如果使用者先解除安裝了舊版本,就會把打包的時候,包含的所有檔案都解除安裝掉。那這樣是不是還要加上一條命令,解除安裝的時候不要把GPExSettings.xml檔案解除安裝掉?

這樣的話,感覺太麻煩了,而且我還是想優先保障打包指令碼的簡單性,不想搞那麼複雜,這種靠命令式的指令碼,總感覺不那麼靈活,所以我們就在程式碼中想辦法。

2、在程式碼中解決

我們可以在程式碼中建立GPExSettings_Bak.xml檔案,可以稱該檔案為GPExSettings.xml的初始或者備份檔案。程式碼在讀取GPExSettings.xml內容的時候,先判斷GPExSettings.xml檔案是否存在,如果存在,則直接讀取,不存在,則拷貝GPExSettings_Bak.xml檔案,重新命名為GPExSettings.xml,再讀取。

並且打包的時候,不要把GPExSettings.xml打進去,只打包GPExSettings_Bak.xml檔案,這樣就不會存在安裝更新包會把使用者設定後的GPExSettings.xml給覆蓋掉,也不會出現解除安裝的時候把GPExSettings.xml檔案解除安裝掉,就達成了我們的目的。

程式碼如下。

private static readonly string _XmlFilePath = AppDomain.CurrentDomain.BaseDirectory + "Res\\GPExSettings.xml";
private static readonly string _BakXmlFilePath = AppDomain.CurrentDomain.BaseDirectory + "Res\\GPExSettings_Bak.xml";
/// <summary>
/// 執行器的設定資訊
/// </summary>
static GPExSettings()
{
    if (File.Exists(_XmlFilePath) == false)
    {
        if (File.Exists(_BakXmlFilePath) == false)
        {
            throw new ArgumentException("GPExSettings_Bak.xml file not exist.");
        }
        File.Copy(_BakXmlFilePath, _XmlFilePath);
    }
    try
    {
        XmlDocument myXmlD = new XmlDocument();
        myXmlD.Load(_XmlFilePath);
        XmlNode myXmlNode = myXmlD.ChildNodes[0];
        ArcPythonPath = myXmlNode.Attributes["ArcPythonPath"].Value;
        IsUseArcPython = Convert.ToBoolean(myXmlNode.Attributes["IsUseArcPython"].Value);
    }
    catch (Exception ex)
    {
        throw new ArgumentException("Load GPExSettings.xml fail," + ex.Message);
    }
}