none
XmlDocument.Save方法 儲存路徑不對 RRS feed

  • 問題

  • 以下這個是我自行設計的一個Xml儲存資料的類別,用來儲存程式的一些相關設定值

    public class MySystemSetting { /* saveType須對應到正確的saveAttribute * 1. Function對應 :AutoStart, CanChangeBadgenumber, CoverOldUserData * 2. HttpServer對應:IP, Port * 3. Language對應 :LanguageIndex * 4. Database對應 :ConnectString */ public enum SaveType { Function, HttpServer, Language, Database }; public enum SaveAttribute { AutoStart, CanChangeBadgenumber, CoverOldUserData, IP, Port, LanguageIndex, ConnectString }; //各種private屬性 private static XmlDocument myXmlDoc; //系統設定參數的Xml檔 private static string myXmlPath = "./SysData.xml"; //系統設定Xml的儲存相對路徑 private static string noteName_Root = "SysRoot"; //此設定檔的父節點 //公開的方法 public static void ReadSetting() //讀取設定 {     //...讀取Xml檔案,如果為null則先初始化

                if (myXmlDoc == null)
                    myXmlDoc = new XmlDocument();
                //判斷檔案是否存在
                if (File.Exists(myXmlPath) == true)
                {
                    myXmlDoc.Load(myXmlPath);
                }
                else
                {
                    //...一些處理
                }

    } //讀取設定值的方法 public static string GetSettingValue(SaveType noteType, SaveAttribute attribute) { string getData = null; try { //選擇節點 XmlNode myNode = myXmlDoc.SelectSingleNode(noteName_Root + "/" + noteType); //如果選擇的節點為null就return null if (myNode == null) return null; //取得節點內屬性 XmlElement myElement = (XmlElement)myNode; //取得指定屬性的數值 getData = myElement.GetAttribute(attribute.ToString()); } catch (Exception err) { throw err; } return getData; } //儲存設定值的方法 public static bool SetSettingValue(SaveType noteType, SaveAttribute attribute, string value) { bool returnValue = false; try { //選擇節點 XmlNode myNode = myXmlDoc.SelectSingleNode(noteName_Root + "/" + noteType.ToString()); //如果選擇的節點為null就return null if (myNode == null) returnValue = false; //取得節點內欄位 XmlElement myElement = (XmlElement)myNode; myElement.SetAttribute(attribute.ToString(), value); myXmlDoc.Save( myXmlPath); returnValue = true; } catch (Exception err) { throw err; } finally { } return returnValue; } }

    然後這是我的XML的結構

    - <SysRoot>
      <Function AutoStart="False" CanChangeBadgenumber="False" CoverOldUserData="False" /> 
      <HttpServer IP="" Port="8080" /> 
      <Language LanguageIndex="0" /> 
      <Database ConnectString="B841B7B2DE4DB44BDF79C6322367C800CA3C44AABA8C09B31FB68068C490C8B553C3D2D68B50672CAB256FB45FCEC3DB6A0FCD69F33A2FC935FE8B6098DF4E698DD152A43DC4DF9BA4A86838ED49783E430AD10974DD64AE" /> 
      </SysRoot>

    其中我的Xml檔的儲存路徑為 :./SysData.xml

    然後今天當我更改設定重新儲存Xml檔時,應該要存到我的指定路徑

    但是我到我的程式資料夾底下發現Xml檔的內容卻沒有被改變,然後在路徑C:\,

    底下卻冒出一個我剛剛儲存的設定檔,而不是存在我指定的路徑底下

    //--修正一下問題內容,剛剛再測試後發現儲存的位置都跑掉了--




    • 已編輯 wingol 2012年9月13日 上午 07:59
    2012年9月13日 上午 06:56

解答

  • 請問您有範例可供我們測試嗎?

    不然就要直接使用「System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Application.ExecutablePath), "SysData.xml"」應該就不會有相對Path的問題了!

    另外,網路上有人提到說「OpenFileDialog, saveFileDialog」會影響到CurrentDirectory,但我是測試不出來,也一併給您參考看看,謝謝!

    Environment.CurrentDirectory in C#.NET


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/


    • 已編輯 亂馬客 2012年9月17日 上午 02:09
    • 已標示為解答 wingol 2012年9月25日 上午 03:42
    2012年9月17日 上午 02:04
  • 不是作業系統的問題,而是搞錯GetCurrentDirectory的使用時機了這個值會在使用檔案管理元件時改變。

    另外,對你的執行檔建立捷徑後,去修改"開始位置"欄位的路徑,GetCurrentDirectory() 的初始值就會指向那邊

    • 已標示為解答 wingol 2012年9月25日 上午 03:42
    2012年9月20日 下午 07:27

所有回覆

  • 然後這是我其中用來建立連線字串的方法

    private void BuildDatabaseConnectStr() { MSDASC.DataLinks dataLinks = new MSDASC.DataLinks(); ADODB.Connection connection = new ADODB.Connection();

      //取得在Xml裡的連線字串,此字串是有加密過的 string getConnStr = MySystemSetting.GetSettingValue(MySystemSetting.SaveType.Database, MySystemSetting.SaveAttribute.ConnectString); //判斷字串是為空

    if (String.IsNullOrEmpty(getConnStr) == true) { getConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=./AdmsAtt.mdb;Persist Security Info=False"; } else { getConnStr = MyFormUIClass.DecryptDES(getConnStr);//解密 } connection.ConnectionString = getConnStr; object oConnection = connection; try {  //顯示初設定連線字串的視窗 if ((bool)dataLinks.PromptEdit(ref oConnection))//prompt user to edit the given connect string { //取得連線字串 getConnStr = connection.ConnectionString; //取得連線字串加密後的字串 string newConnStr = MyFormUIClass.EncryptDES(connection.ConnectionString); //重新初始化資料庫處理物件 DbDataHandle.InitialDbComponent(connection.ConnectionString); this.InitialListViewAndHash(); //視窗裡的一些初始化方法 //儲存連線字串 MySystemSetting.SetSettingValue(MySystemSetting.SaveType.Database, MySystemSetting.SaveAttribute.ConnectString, newConnStr); } } catch (Exception err) { MessageBox.Show(err.Message, MyLanguageClass.Title_Err); } }

    然後我在除錯模式設了中斷點一步步的觀看,然後發現XmlDocument物件資料都有寫進入,

    但不知為何最後的儲存路徑卻錯了不是在我指定的位置上

    2012年9月13日 上午 07:25
  • 您好,
    您可以看一下實際的Path是在那裡哦!

    請使用「MessageBox.Show(System.IO.Path.GetFullPath(myXmlPath));」看一下吧!

    不過,
    您的Path好像錯邊了哦!

    private static string myXmlPath = @"./SysData.xml";
    =>
    private static string myXmlPath = @".\SysData.xml";



    如果要取執行路徑下的Path,可透過以下的方式來取到Path

    MessageBox.Show( System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Application.ExecutablePath), "SysData.xml"));


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/


    • 已編輯 亂馬客 2012年9月13日 上午 10:15
    2012年9月13日 上午 10:08
  • 那個路徑不管是

    private static string myXmlPath = @"./SysData.xml";
    =>
    private static string myXmlPath = @".\SysData.xml";

    其實好像都是可以通用的

    然後我嘗試著去使用像System.IO.Path.GetFullPath , System.IO.Directory.GetCurrentDirectory

    一開始抓取的路徑的確是正確的,但到後來像是在儲存我的連線字串時,

    此時回傳的路徑已經自己莫名其妙跑到C:\去了,具體的原因暫時也不知道

    然後現在的解決辦法是在當我一開始程式剛執行時立刻去抓取該XML檔案的絕對路徑,

    然後額外儲存在一個變數裡,然後程式執行期間就依照該絕對路徑下去儲存XML而不去參照原本的相對路徑

    只不過相對路徑錯誤的問題可能還要再測試測試~"~


    2012年9月14日 上午 05:43
  • 您好,
    請問您的程式中,有改到 System.Environment.CurrentDirectory 這個值嗎?

    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2012年9月14日 上午 06:54
  • 基本上是沒有,頂多只有用到使用到像類似GetFullPath像這一類取得路徑的方法而已

    2012年9月17日 上午 01:39
  • 請問您有範例可供我們測試嗎?

    不然就要直接使用「System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Application.ExecutablePath), "SysData.xml"」應該就不會有相對Path的問題了!

    另外,網路上有人提到說「OpenFileDialog, saveFileDialog」會影響到CurrentDirectory,但我是測試不出來,也一併給您參考看看,謝謝!

    Environment.CurrentDirectory in C#.NET


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/


    • 已編輯 亂馬客 2012年9月17日 上午 02:09
    • 已標示為解答 wingol 2012年9月25日 上午 03:42
    2012年9月17日 上午 02:04
  • 剛剛我測試了一下發現路徑問題真的是來自於使用像OpenFileDialog這種效果的物件or方法造成的

    我的測試環境是在Windows XP底下,至於在Win7 or Server這些會不會有一樣的問題就不清楚了

    我剛剛額外弄了一個測試專案上傳到sky Drive : 測試下載,裡面的ThePathTest就是了

    //

    然後我是使用System.IO.Directory.GetCurrentDirectory測試

    我查閱了一下MSDN的關於這方法的說明,MSDN是寫說"取得應用程式的目前工作目錄"

    然後我想了一下他的真正用途然在於取得"目前"工作目錄

    所以如果用到像是OpenFileDialog這一類的東西然後再使用GetCurrentDirectory

    他的路徑其時隨時都在變的

    比如現在我的程式現在位置在 C:\我的程式,如果今天我使用到有像OpenFileDialog選擇一個東西

    比如路徑是D:\我要的東西,此時再度呼叫GetCurrentDirectory他的路徑其實會取得到D:\底下去了

    此時如果你使用像是相對路徑的方式去存取你的檔案,這時的相對路徑也會取得到D:\這個地方了

    所以如果真的要取得你的程式實際運作的地方,正確的用法應該要使用Application.ExecutablePath

    使用Application底下的屬性來取得你的路徑才是正確的做法,而不是GetCurrentDirectory

    所以其實我一直應該都是誤解了GetCurrentDirectory 的使用方法了

    2012年9月17日 上午 04:18
  • 您在XP上測試按下button2後,System.IO.Directory.GetCurrentDirectory會變掉呀!

    我的環境是Win7不會變掉哦!

    就像「Environment.CurrentDirectory in C#.NET」說的一樣,改用別的方式來取Path吧!


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2012年9月17日 上午 04:45
  • 我在XP上的確是會有路徑變掉的問題

    看來就是作業系統上造成的差異了,看來還是改用別的方式來取得路徑會比較保險

    2012年9月17日 上午 05:02
  • 不是作業系統的問題,而是搞錯GetCurrentDirectory的使用時機了這個值會在使用檔案管理元件時改變。

    另外,對你的執行檔建立捷徑後,去修改"開始位置"欄位的路徑,GetCurrentDirectory() 的初始值就會指向那邊

    • 已標示為解答 wingol 2012年9月25日 上午 03:42
    2012年9月20日 下午 07:27