Microsoft Server 2008 / 2012 工作排程器 無法正常執行 C# [.NET] 程式

這個問題是我常常遇到的,很多時候寫Server端的程式通常是需要配合排程(工作排程器)執行的。

而這個工作排程器好似從2008以後的版本就跟2003有不少差異。

但就寫程式的工程師而言,有一個非常要注意的地方,那就是『程式執行位置』,底下演示一段程式碼來顯示正常情況下,你的程式取得的程式所在位置資訊

我的程式位置在 D:\TEST 11\CnetAppPath


string dir = System.Environment.CurrentDirectory;
位置:D:\TEST 11\CnetAppPath

string dir = System.Windows.Forms.Application.StartupPath;
位置:D:\TEST 11\CnetAppPath

string dir = System.IO.Directory.GetCurrentDirectory();
位置:D:\TEST 11\CnetAppPath

string dir = System.AppDomain.CurrentDomain.BaseDirectory;
位置:D:\TEST 11\CnetAppPath\

string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
位置:D:\TEST 11\CnetAppPath\

string dir = System.Windows.Forms.Application.ExecutablePath;
位置:D:\TEST 11\CnetAppPath\AppPath.exe

string dir = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
位置:D:\TEST 11\CnetAppPath\AppPath.exe

string dir = this.GetType().Assembly.Location;
位置:D:\TEST 11\CnetAppPath\AppPath.exe


假設,我建立一個捷徑,一般情況下捷徑裡面會有一個設定值『開始位置』,如果變更了這個『開始位置』,那某些路徑取得就會發生變化:



string dir = System.Environment.CurrentDirectory;
位置:C:\

string dir = System.Windows.Forms.Application.StartupPath;
位置:D:\TEST 11\CnetAppPath

string dir = System.IO.Directory.GetCurrentDirectory();
位置:C:\

string dir = System.AppDomain.CurrentDomain.BaseDirectory;
位置:D:\TEST 11\CnetAppPath\

string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
位置:D:\TEST 11\CnetAppPath\

string dir = System.Windows.Forms.Application.ExecutablePath;
位置:D:\TEST 11\CnetAppPath\AppPath.exe

string dir = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
位置:D:\TEST 11\CnetAppPath\AppPath.exe

string dir = this.GetType().Assembly.Location;
位置:D:\TEST 11\CnetAppPath\AppPath.exe


看起來,dotNet 對 CurrectDirectory 的概念有不同的詮釋,對於有學其他語言程式的人,很容易造成有殺傷力的誤解。

在 dotNet 中 CurrectDirectory 是對應到『開始位置』,而不是『程式所在位置』。

那這個跟工作排程有甚麼關係呢?

在Windows 2003下,其工作排程指定的執行程式時,通常很貼心的自動幫你把執行程式所在位置套用在『開始位置』,所以你在新增工作排程時,其時不會特別要去設定它。


但是,在Server 2008以後的工作排程,在新增排程工作後,通常都沒有自動產生『開始位置』,這種情況下,設定人員除非他本身就是寫這程式的,否則也不太會主動去設定這個欄位,所以通常會讓這欄位空白。



所以實際上這個情況下下列程式碼取得的內容就會跑掉,因此我們在撰寫程式在使用取得資源指令時,要慎選指令以免發生無法預期的問題:

string dir = System.Environment.CurrentDirectory;
位置:C:\Windows\system32

string dir = System.Windows.Forms.Application.StartupPath;
位置:D:\TEST 11\CnetAppPath

string dir = System.IO.Directory.GetCurrentDirectory();
位置:C:\Windows\system32

string dir = System.AppDomain.CurrentDomain.BaseDirectory;
位置:D:\TEST 11\CnetAppPath\

string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
位置:D:\TEST 11\CnetAppPath\

string dir = System.Windows.Forms.Application.ExecutablePath;
位置:D:\TEST 11\CnetAppPath\AppPath.exe

string dir = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
位置:D:\TEST 11\CnetAppPath\AppPath.exe

string dir = this.GetType().Assembly.Location;
位置:D:\TEST 11\CnetAppPath\AppPath.exe


PS:當你有設定『起始位置』這不會是個問題,但是通常大公司寫程式和設定伺服器的資訊人員是不一樣的,當然也不會有一樣的 Sense,所以寫程式的人要學會把程式寫精準一點避免被別人挑戰這種莫名的問題。

我想你應該懂的....






留言

這個網誌中的熱門文章

【研究】列印的條碼為什麼很難刷(掃描)

C# 使用 Process.Start 執行外部程式

統一發票列印小程式