用 .net 的 console 模式寫了一個 .exe 檔,在自己電腦上直接執行,是正常的,主要功能是讀取同個資料夾下面的 xml 檔,並進行後面的一些處理工作。但奇怪的是,當我使用電腦排程去呼叫 .exe 檔時,就會在排程表裡面發現所建立的排程一直處於「執行中」的狀態,且這個現象一直都不會停止,由於我是設成每天都要執行,所以當第二天的同個時間要執行時,就會出現錯誤,理由是先前的工作尚未結束,所以無法再做新的。這理由我倒覺得合理,但問題是,為何第一天執行的程式遲遲無法結束呢?心裡第一個念頭,是該不會在裡面給我跑無限迴圈吧!!
就在自己含淚一行一行的檢查程式之餘,發現原來程式是停在下面這一行:
System.Console.ReadLine();
原先是我用來判斷是否使用者有正確的擺放 xml 檔到執行程式的資料夾,沒有的話就會跳出訊息,並將執行畫面暫停,等待輸入「Enter」鍵之後再繼續執行。只是這作法,放到 windows 排程裡,就會造成系統為了要等待輸入「Enter」而停在那一直無法結束,其實程式不是在跑無限迴圈,而是無限等待。
然而,真正產生問題的原因,並不只是因為自己誤用了 ReadLine()而已,最主要的問題是為何會找不到 xml 檔呢,我用我的兩隻眼睛的確在執行檔的資料夾下面都有看到啊。在網路上有看到許多人在討論 windows 排程無法正常執行的討論議題,其中「Windows server 2008 排程無法執行」這一篇有提到,如果有對檔案進行存取動作時,要使用完整路徑,否則他可能預設會用 C:\Windows\System32 資料夾來處理。我測試了一下,的確如此,假設我是直接去執行 .exe 檔,則他就會以執行檔所在路徑來處理,但使用排程時,就變成 C:\Windows\System32 了。
我在程式裡面有使用到
DataSet dsConfig=new DataSet(); string strFileName="setup.xml"; if(System.IO.File.Exists(strFileName)) { dsConfig.ReadXml(strFileName); }
這寫法很不幸的,在使用 windows 排程時會發生找不到 xml 檔的問題。
於是我改用完整路徑的方法來改善。
首先,透過 GetExecutingAssembly().Location 取得執行檔的完整檔名路徑
System.Reflection.Assembly.GetExecutingAssembly().Location
接著只取執行檔的完整路徑(不含檔名)
Path.GetDirectoryName(FileName)
所以修改後的程式就變成:
DataSet dsConfig=new DataSet(); //取得執行路徑 string strExecPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); //取得 .xml 設定檔完整路徑,windows 排程需使用完整路徑設定 string strFullPath=string.Format("{0}\\{1}",strExecPath,setupFile); if(System.IO.File.Exists(strFullPath)) { dsConfig.ReadXml(strFullPath); }
原來,將程式改寫為 windows 排程,還需要考慮是否使用「完整路徑」的問題啊!
參考:Windows server 2008 排程無法執行
解決了我的疑惑
回覆刪除謝謝您