2013年3月25日 星期一

project has not been confiured



剛接手一個 VS2010 的專案,想說都是同樣的開發工具所開發的,應該沒什麼問題吧!結果專案一打開,竟跳出個我很陌生的錯誤訊息,然後該專案就無法開啟。

錯誤訊息如下:
The local IIS URL http://localhost/XXX specified for Web project XXX has not been confiured. In order to open this project the virtual directory needs to be configured. Would you like to create the virtual directory now?



從錯誤訊息看起來,是因為這個專案是採用 Web Site 模式開發,但在我的 IIS 裡面找不到相對應的虛擬目錄。原來這專案當初在命名時,可能使用 OOO,但對應的網站虛擬目錄卻是用 XXX,難怪我一開始根據專案名稱來建虛擬目錄時會建錯。

這時候有兩個解決方法,第一個最簡單,就是去更改 IIS 的設定,將 IIS 的虛擬目錄名稱改為 XXX。第二個,則是自己比較陌生的方法,但其實也不難。只要在無法載入的專案上按右鍵,就會出現 Edit OOO.csproj  的選項,點選進去後,會出現一份 xml 格式的設定檔,找到 <IISUrl>,把他註解掉(mark)或改成 http://localhost/XXX ,再重新載入一次專案就可以了。

是不是採用註解 (mark)掉的方式,差別在於:

用註解掉(mark)的方式,程式在執行時,他會透過虛擬一個網站的方式,以 http://localhost:1234/XXX 來呈現。
<!--<IISUrl>http://localhost/XXX</IISUrl>-->

但如果你的 IIS 裡早就已經設定好網站路徑,則可以將 OOO.csproj 裡的 IISUrl 改成正確的位置即可。程式執行實則會是: http://localhost/XXX

參考:The local IIS URL specified for Webproject has not been configured.

2013年3月18日 星期一

Windows 排程無法執行


用 .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 排程無法執行