摘要 :
       有時候,處于業務的需要,我們要不斷的監視文件的變化,比如文件的創建、刪除、重命名等;而且某些人要確保重要文件的只讀,并且要及時的報告文件版本的變更情況。或者,你想監視你的文件夾被別人更改、肆意刪除而又不知道是誰干的,在什么時候干的?于是你就考慮要寫一個監視程序,“偷偷的”記錄文件夾被操作的情況。
       有些人采取常規的方式,即寫一個桌面應用程序,其界面可能是隱藏的。采用每隔一個事件片段讀取文件信息,然后寫到一個log文件中。然后設置系統啟動的事件自動加載程序,(好像很多人是這樣竊取qq密碼的:()。其缺點:1、不是連續的獲取信息,因為他們采用了timer的tick事件;2、在nt系統中,可能要一定的權限才可以運行,比如要管理員身份等。還有系統中會有進程顯示,顯然很容易shutdown.
       我們建議的方案:采用.net的windows service。首先可以克服以上缺點,而且較vb6的編程而言,.net中寫windows service一如反掌。
思路:
       在.net創建的服務中調用system.io.filesystemwatcher對象,每次被監視的文件或者文件夾變化的時候,調用io系統的filestream和streamwriter把變更信息寫到log文件中。
正文:
       關于.net中的windows服務:
       windows服務,是一些長久運行的程序,而并不需要依靠登錄用戶或客戶程序來保持它的運行。它們沒有自己的用戶界面,可以在它們自己獨有的安全級別和會話上下文中運行。我們比較熟悉的windows服務范例包含了從打印池到sql服務器以及它的分布式事務協作(dtc)。服務只可以運行在nt、2000以及后繼產品比如xp下運行,它們通過microsoft management console (mmc)提供了一個專門的管理界面(開始->運行->services.msc)。
       在.net中創建項目的時候,有一個windows服務的模板,選擇新建。這個操作自動為我建立了一個新的類,它是繼承了.net內建了system.serviceprocess.servicebase類。同時它提供給我一個可視化的設計器,一個圖形化的快速開發工具,它特別的為那些本身沒有用戶界面的工程。我可以點擊這個設計器,設定我的服務的名字(我命名為"file watching")。
       當啟動某項服務時,系統將定位相應的可執行文件,并運行該服務的 onstart 方法(它包含在可執行文件內)。但是,運行服務與運行可執行文件并不相同。可執行文件僅加載服務。服務則通過“服務控制管理器”訪問(例如啟動和停止)。
       當首次在服務上調用“開始”時,可執行文件將調用 servicebase 派生類的構造函數。在構造函數執行之后將立即調用 onstart 命令處理方法。在服務首次加載之后,構造函數不會再次執行,因此有必要將構造函數執行的處理和 onstart 執行的處理分開。可以由 onstop 釋放的任何資源都應在 onstart 中創建。如果服務在 onstop 釋放資源后再次啟動,那么,在構造函數中創建資源會妨礙這些資源的正確創建。
       “服務控制管理器”(scm) 提供與服務交互的方式。可以使用 scm 將“開始”(start)、“停止”(stop)、“暫停”(pause)、“繼續”(continue) 或自定義命令傳遞到服務中。scm 使用 canstop 和 canpauseandcontinue 的值,決定服務是否接受“停止”、“暫停”或“繼續”命令。僅當服務類中相應的屬性 canstop 或 canpauseandcontinue 為 true 時,才會在 scm 的上下文菜單中啟用“停止”、“暫停”或“繼續”。如果已啟用,則相應的命令將傳遞到服務,并且調用 onstop、onpause 或 oncontinue。如果 canstop、canshutdown 或 canpauseandcontinue 為 false,則即使已實現相應的命令處理方法(如 onstop),也不會予以處理。
       上面是創建任何一個服務,我們都會涉及到的只是,具體在監視文件夾變化的時候,我們用到了filesystemwatcher。
關于filesystemwatcher:
       偵聽文件系統更改通知,并在目錄或目錄中的文件發生更改時引發事件。
       使用 filesystemwatcher 監視指定目錄中的更改。可監視指定目錄中的文件或子目錄的更改。該組件可以監視本地計算機、網絡驅動器或遠程計算機上的文件。(當然只讀的媒體介質比如cd和dvd,它們文件的屬性不會改變,所以也就不能觸發事件)
       若要監視所有文件中的更改,請將 filter 屬性設置為空字符串 ("")。若要監視特定的文件,請將 filter 屬性設置為該文件名。例如,若要監視文件 mydoc.txt 中的更改,請將 filter 屬性設置為“mydoc.txt”。也可以監視特定類型文件中的更改。例如,若要監視文本文件中的更改,請將 filter 屬性設置為“*.txt”。
       可監視目錄或文件中的若干種更改。例如,可監視文件或目錄的 attributes、lastwrite 日期和時間或 size 方面的更改。通過將 filesystemwatcher.notifyfilter 屬性設置為 notifyfilters 值之一來達到此目的。
       可監視文件或目錄的重命名、刪除或創建。例如,若要監視文本文件的重命名,請將 filter 屬性設置為“*.txt”,并調用 waitforchanged 方法之一,調用時給出 watcherchangetypes 值的 renamed。
demo:
       新建一個project,選擇windows 服務類型,命名為winservicefilewatching,我們看到project的引用中自動添加了system.serviceprocess名空間(這就是創建一個服務的函數集)。從工具中的組件中選擇filesystemwatcher1,拖放到service1的設計模式上,然后設置如下屬性:
       filter 獲取或設置篩選字符串,用于確定在目錄中監視哪些文件。 我們設置為*.*,即所有文件
       includesubdirectories 獲取或設置一個值,該值指示是否監視指定路徑中的子目錄。 設置為true
       path 獲取或設置要監視的目錄的路徑             設置為我們要監視的對象,比如c:/donnetdata
       然后添加以下代碼:
protected overrides sub onstart(byval args() as string)
        ' 在此處添加啟動服務的代碼。此方法應設置具體的操作
        ' 以便服務可以執行它的工作。
        filesystemwatcher1.enableraisingevents = true
       ' 我們也可以根據輸入的參數args動態設定要監視的對象
       'filesystemwatcher1.path= args(0)
end sub
' 創建文件(夾)時候觸發,記錄創建信息到e:/log.txt中
private sub filesystemwatcher1_created(byval sender as object, byval e as system.io.filesystemeventargs) handles filesystemwatcher1.created
        dim fs as new filestream("e:/log.txt", filemode.append)
        dim sw as new streamwriter(fs)
        sw.writeline(now() & microsoft.visualbasic.vbtab & "創建" & e.fullpath)
        sw.close()
        fs.close()
end sub
' rename文件(夾)時候觸發,記錄創建信息到e:/log.txt中 
private sub filesystemwatcher1_renamed(byval sender as object, byval e as system.io.renamedeventargs) handles filesystemwatcher1.renamed
        dim fs as new filestream("e:/log.txt", filemode.append)
        dim sw as new streamwriter(fs)
        sw.writeline(now() & microsoft.visualbasic.vbtab & "重命名" & e.oldfullpath & "-" & e.fullpath)
        sw.close()
        fs.close()
end sub
' 刪除文件(夾)時候觸發,記錄創建信息到e:/log.txt中
private sub filesystemwatcher1_deleted(byval sender as object, byval e as system.io.filesystemeventargs) handles filesystemwatcher1.deleted
        dim fs as new filestream("e:/log.txt", filemode.append)
        dim sw as new streamwriter(fs)
        sw.writeline(now() & microsoft.visualbasic.vbtab & "刪除" & e.fullpath)
        sw.close()
        fs.close()
end sub  
到目前為止,這個服務已經寫好了,下面作一個安裝程序:
       在service的設計模式上點擊右鍵,選擇添加安裝程序。系統會自動添加一個類projectinstaller,設計模式上有一個serviceprocessinstaller1 和serviceinstaller1。設置serviceinstaller1的display name為file watching service,starttype為automatic,表示自動啟動。設置serviceprocessinstaller1 的account為localsystem。
由于服務是不能運行的,我們選擇生成解決方案。ok!
最后安裝我們的服務:
       .net framework自帶了一個工具,installutil,使用很簡單installutil c:/winservicefilewatching/bin/winservicefilewatching.exe ' 剛才編譯好的程序的路徑
       這樣就安裝好了,uninstall也很容易。首先scm中關閉服務,installutil/u c:/.../winservicefilewatching.exe 'the same path
這樣在系統的services中就會多出一個服務,顯示為file watching service,選擇啟動就可以開始監視... 
       總結:
       在.net創建的服務中調用system.io.filesystemwatcher對象,每次被監視的文件或者文件夾變化的時候,調用io系統的filestream和streamwriter把變更信息寫到log文件中。實際上利用了.net強大的內置集成功能,把復雜的文件簡單話。
新聞熱點
疑難解答
圖片精選