C#Windows服務(wù)程序編寫_第1頁
C#Windows服務(wù)程序編寫_第2頁
C#Windows服務(wù)程序編寫_第3頁
C#Windows服務(wù)程序編寫_第4頁
C#Windows服務(wù)程序編寫_第5頁
已閱讀5頁,還剩40頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、C#發(fā)現(xiàn)之旅 - C#開發(fā)Windows Service程序本課程說明了Windows Service程序的概念,并演示如何使用C#開發(fā)一個(gè)簡單的Windows Service程序。C#工程名為MyWindowsService,編譯生成的文件是MyWindowsService.exe。本課程的演示代碼下載地址為Windows Service概念介紹Windows Service,也稱Windows服務(wù),是32位Windows操作系統(tǒng)中一種長期運(yùn)行的后臺(tái)程序。它們長期后臺(tái)運(yùn)行,沒有用戶界面,默默無聞,但它們卻是支持Windows正常運(yùn)行的幕后英雄,卻永無出頭之日。Windows服務(wù)程序?yàn)槠渌到y(tǒng)

2、模塊提供了非常重要的服務(wù),而且各個(gè)Windows服務(wù)分工明確,比如IISAdmin服務(wù)提供WEB內(nèi)容的發(fā)布功能,若IISAdmin服務(wù)不啟動(dòng),則靜態(tài)HTML頁面、ASP、ASP.NET或者WebService等等統(tǒng)統(tǒng)不行;有個(gè)名為“Print Spooler”的服務(wù)用于提供打印支持,若該服務(wù)不啟動(dòng),則任何軟件都不能進(jìn)行打印,比如Word,記事本或者報(bào)表軟件等等。Windows啟動(dòng)后在沒有用戶登錄時(shí)就會(huì)啟動(dòng)Windows服務(wù)。Windows NT和Windows2000,以及更新的版本操作系統(tǒng)能運(yùn)行Windows服務(wù),但Windows98及其前期版本是不能運(yùn)行服務(wù)的。我們打開Windows資源管

3、理器,在左邊的樹狀列表中選中“桌面-控制面板-管理工具”。 在右邊的列表中打開“服務(wù)”項(xiàng)目即可打開Windows服務(wù)管理器。 在這些服務(wù)中,有我們最熟悉的IIS Admin和World Wide Web Publishing服務(wù)了。我們雙擊一個(gè)服務(wù)項(xiàng)目即可打開服務(wù)屬性對(duì)話框。 Windows服務(wù)有一個(gè)服務(wù)名稱屬性,該屬性是服務(wù)的惟一的不可重復(fù)的名稱,我們可以在命令行中使用命令“net start 服務(wù)名稱”來啟動(dòng)服務(wù),使用“net stop 服務(wù)名稱”來停止服務(wù)。Windows服務(wù)的啟動(dòng)類型有自動(dòng),手動(dòng)和已禁用。當(dāng)啟動(dòng)類型為自動(dòng)時(shí),Window

4、s啟動(dòng)后不等用戶登錄就自動(dòng)啟動(dòng)服務(wù),當(dāng)啟動(dòng)類型為手動(dòng)時(shí),需要某個(gè)操作員登錄后點(diǎn)擊這里的“啟動(dòng)”按鈕來啟動(dòng)服務(wù),而當(dāng)啟動(dòng)類型為已禁用時(shí),Windows服務(wù)不能啟動(dòng)。該頁面中的“啟動(dòng)”按鈕用于啟動(dòng)尚未啟動(dòng)的Windows服務(wù),運(yùn)行提供服務(wù)的進(jìn)程;“停止”按鈕用于停止已經(jīng)啟動(dòng)的服務(wù),殺死服務(wù)進(jìn)程;而“暫?!卑粹o用于通知服務(wù)進(jìn)程暫時(shí)停止提供服務(wù),但服務(wù)進(jìn)程依然存在;而“恢復(fù)”按鈕用于通知處于暫停模式的服務(wù)進(jìn)程重新提供服務(wù)。       我們可以查看服務(wù)屬性對(duì)話框的“登錄”頁面。 可以指定服務(wù)使用本地系統(tǒng)帳戶登錄,也可另外指

5、定其他的用戶,這里有一個(gè)允許服務(wù)和桌面交互的選項(xiàng),若選中此選項(xiàng),則Windows服務(wù)可以顯示圖形化用戶界面,比如顯示自己的窗體,顯示消息框等等。不過不建議使用該選項(xiàng),而且Windows服務(wù)運(yùn)行時(shí)不要顯示圖形化用戶界面。我們切換到“依存關(guān)系”頁面,可以看到本服務(wù)和其他服務(wù)的依存關(guān)系。 各個(gè)Windows服務(wù)之間可能存在依賴關(guān)系,比如IISADMIN服務(wù)就依賴另外一個(gè)名為RPC的Windows服務(wù),當(dāng)啟動(dòng)一個(gè)Windows服務(wù)時(shí),系統(tǒng)會(huì)啟動(dòng)該服務(wù)所依賴的其他Windows服務(wù)。例如我們設(shè)置IISADMIN服務(wù)為自動(dòng)啟動(dòng),而RPC服務(wù)為手動(dòng)啟動(dòng),則Windows啟動(dòng)后會(huì)試圖自動(dòng)啟動(dòng)IISA

6、DMIN服務(wù),結(jié)果會(huì)首先啟動(dòng)RPC服務(wù),即使RPC服務(wù)不是自動(dòng)啟動(dòng)。若RPC服務(wù)為禁止,無論如何也不能啟動(dòng),則IISADMIN服務(wù)就無法自動(dòng)啟動(dòng)了。C#編寫Windows服務(wù)的基本過程編寫Windows服務(wù)是一種比較高級(jí)的編程技術(shù),內(nèi)部使用了很多Windows操作系統(tǒng)的核心功能,但微軟.NET框架已經(jīng)很好的封裝了這些技術(shù)細(xì)節(jié),使得我們可以很方便的使用C#編寫自己的Windows服務(wù),其基本過程一般為1.       創(chuàng)建C#工程。創(chuàng)建一個(gè)EXE工程,可以是WinForm或者命令行格式的。添加對(duì)System.ServicePr

7、ocess.dll和System.Configuration.Install.dll的引用。2.       創(chuàng)建服務(wù)類。新增一個(gè)類,該類型繼承System.ServiceProcess.ServiceBase類型,在構(gòu)造函數(shù)中設(shè)置ServiceName屬性來指明該服務(wù)的名稱。然后重載它的OnStart方法來響應(yīng)啟動(dòng)服務(wù)的事件,重載OnStop方法來響應(yīng)停止服務(wù)的事件,重載OnPause方法來響應(yīng)暫停服務(wù)的事件,重載OnContinue方法來響應(yīng)恢復(fù)提供服務(wù)的事件。在重載這些方法時(shí)必須要立即返回,其中不能出現(xiàn)長時(shí)間的操作,若

8、處理時(shí)間過長則Windows服務(wù)管理器會(huì)覺得該Windows服務(wù)停止響應(yīng)而報(bào)錯(cuò)。為此我們可以使用一個(gè)線程來進(jìn)行實(shí)際的工作,而OnStart方法創(chuàng)建線程,OnStop方法關(guān)閉線程,OnPause方法掛起線程,而OnContinue方法來恢復(fù)運(yùn)行線程。3.       啟動(dòng)服務(wù)。在main函數(shù)中調(diào)用“System.ServiceProcess.ServiceBase.Run( 自定義服務(wù)類的實(shí)例 )”來運(yùn)行服務(wù)。比如“System.ServiceProcess.ServiceBase.Run( new MyS

9、ervice() )”,這里的MyService就是繼承自ServiceBase。4.       安裝服務(wù)。新增一個(gè)類,該類型繼承自System.Configuration.Install.Installer類型,該類型用于配合微軟.NET框架自帶的安裝命令行工具InstallUtil.exe的。我們?yōu)樵擃愋透郊覵ystem.ComponentModel.RunInstallerAttribute特性,并在它的構(gòu)造函數(shù)中使用System.ServiceProcess.ServiceInstaller對(duì)象和System.Se

10、rviceProcess.ServiceProcessInstaller對(duì)象向系統(tǒng)提供該服務(wù)的安裝信息。程序編譯后我們可以使用命令行“InstallUtil.exe   EXE文件名”向Windows服務(wù)管理器注冊服務(wù),可以使用命令行“InstallUtil.exe /u EXE文件名”從Windows服務(wù)管理器中注銷服務(wù)。5.       編寫服務(wù)客戶端。這是一個(gè)根據(jù)實(shí)際情況而可選的過程,由于Windows服務(wù)是沒有用戶界面的,因此我們可以編寫一個(gè)具有用戶界面的程序來顯示和控制Win

11、dows服務(wù)提供的數(shù)據(jù),并進(jìn)行一些系統(tǒng)設(shè)置等操作。比如對(duì)于MS SQL Server,數(shù)據(jù)庫引擎是以服務(wù)的形式存在,而SQL Server企業(yè)管理器就是一個(gè)客戶端軟件。軟件功能需求現(xiàn)在我們要求使用C#和VS.NET2005開發(fā)一個(gè)軟件,該軟件功能為1.       該軟件能監(jiān)視指定目錄下的文件和子目錄的新增,修改,刪除和重命名操作,并將操作日志記錄到一個(gè)數(shù)據(jù)庫中。2.       該軟件以Windows服務(wù)的形式運(yùn)行,能監(jiān)視不同的用戶帳戶的操作記錄。3.&

12、#160;      有一個(gè)客戶端軟件能控制服務(wù),并能查看服務(wù)的保存的監(jiān)視記錄。其用戶界面為客戶端軟件還能設(shè)置服務(wù)監(jiān)視的目錄,系統(tǒng)設(shè)置對(duì)話框?yàn)檐浖O(shè)計(jì)命令行參數(shù)設(shè)計(jì)一般而言,我們將服務(wù)和客戶端分成兩個(gè)C#工程開發(fā),但這里為了方便我們只在一個(gè)工程中實(shí)現(xiàn)服務(wù)器和客戶端軟件的開發(fā)。Windows服務(wù)是不能顯示圖形化用戶界面的,但并不是說Windows服務(wù)的軟件中不能包含顯示圖形化用戶界面的軟件模塊。我們完全可以編寫一個(gè)EXE,其中包含服務(wù)器和客戶端兩個(gè)相互獨(dú)立的軟件模塊。直接執(zhí)行EXE將以服務(wù)模式運(yùn)行,若帶有命令行參數(shù)將以客戶端模式運(yùn)行。為

13、此我們設(shè)計(jì)了如下的命令行參數(shù)命令行參數(shù)功能無任何參數(shù)以服務(wù)模式運(yùn)行,調(diào)用ServiceBase.Run函數(shù)來運(yùn)行服務(wù)。/install調(diào)用InstallUtil.exe安裝服務(wù),將EXE自己注冊到Windows服務(wù)管理器中。/uninstall調(diào)用InstallUtil.exe卸載服務(wù)。/client以客戶端模式運(yùn)行,顯示圖形用戶界面。/debug以調(diào)試模式下運(yùn)行,方便VS.NET對(duì)服務(wù)的操作過程提供調(diào)試。使用VS.NET調(diào)試服務(wù)是一個(gè)比較麻煩的事,首先我們得安裝并運(yùn)行服務(wù),然后使用VS.NET的菜單項(xiàng)目“工具-附加到進(jìn)程”的操作來附加到服務(wù)程序,然后設(shè)置斷點(diǎn)進(jìn)行調(diào)試,其中OnStart函數(shù)是

14、沒有辦法設(shè)置斷點(diǎn)調(diào)試的。為此我們專門添加一個(gè)“/debug”命令行參數(shù)使得程序不進(jìn)入服務(wù)模式,而是直接運(yùn)行提供服務(wù)內(nèi)容的功能性代碼,然后主線程休眠,但功能性代碼還在運(yùn)行,可以調(diào)試。這樣我們在VS.NET中設(shè)置斷點(diǎn)后可以直接運(yùn)行進(jìn)行調(diào)試了。這里我們設(shè)計(jì)的C#工程名稱為MyWindowsService,編譯生成的文件為MyWindowsService.exe。數(shù)據(jù)庫設(shè)計(jì)在本軟件中,數(shù)據(jù)將保存到應(yīng)用程序目錄下的一個(gè)名為FileSystemWatcher.mdb的Access2000格式的數(shù)據(jù)庫。數(shù)據(jù)庫中的表結(jié)構(gòu)為文件系統(tǒng)操作日志表 FileSystemLog,字段有字段名類型說明Recor

15、dID文本(50)記錄編號(hào)WatchTime文本(20)記錄時(shí)間,為yyyy-MM-dd HH:mm:ss格式ObjectName文本(250)對(duì)象名稱EventStyle文本(50)事件類型該數(shù)據(jù)表中保存的數(shù)據(jù)范例為RecordIDWatchTimeObjectNameEventStyle0d4e0d9a-6826-415b-bd47-c86fbb1449b02008-10-02 15:31:27c:"aaaaaa.txtRenamed22c1df6d-4f94-488c-a705-e8024d8752132008-10-02 20:37:03d:"aa.pngRenam

16、ed27632fe8-6cbf-4a41-95ad-6ab2e82221922008-10-02 20:40:56c:"a.pdfCreated48403266-0150-44c8-8efa-169f7a68bcb42008-10-03 11:02:04c:"zzzzzz.bmpRenamed6c3b603a-f43b-415c-8122-4aa23376d5752008-10-02 11:26:57c:"SDC_2008_10_2.logChanged6fb9fad1-51f5-40b2-b05b-d0628f775a3c2008-10-02 15:31:52c

17、:"aaaaaa.txtDeleted735d74e6-1548-4d7d-9048-ab75dd1c58742008-10-02 20:31:27c:"aa.bmpRenamed7b36a079-c56c-48f7-9c6e-cf0d77b9c6c12008-10-02 11:27:12c:"SDC_2008_10_2.logChanged7c2672ac-b210-4eca-9277-2505030e72e52008-10-02 20:39:12d:"aa.pngDeleted9ab95c19-ccd0-43eb-89ec-3930ebec9a8d2

18、008-10-02 21:55:57c:"b.bmpRenamed9adb5696-fb6a-497e-b4ff-06f5da8964342008-10-02 20:39:12d:"1.pngDeleted9f4d702f-57c1-46ec-a827-701c2a15ee812008-10-02 23:59:04c:"新建文件夾Createdc163fa48-f5ea-49b1-95c9-b89f9ee622e52008-10-02 11:26:42c:"新建 文本文檔.txtCreated對(duì)于新增文件或目錄操作其EventStyle值為Cr

19、eated,對(duì)于修改為Changed,對(duì)于刪除為Deleted,對(duì)于重命名為Renamed。 系統(tǒng)設(shè)置信息表 SystemConfig,字段有字段名類型說明ConfigName文本(50)系統(tǒng)配置名稱ConfigValue文本(250)配置數(shù)據(jù)該數(shù)據(jù)表中保存的數(shù)據(jù)的范例為ConfigNameConfigValueLogChangedTrueLogCreatedTrueLogDeletedTrueLogRenamedFalsepath0c:"*.txtpath1d:"       在這里

20、配置項(xiàng)LogChanged表示是否監(jiān)視文件內(nèi)容是否被改變事件,配置項(xiàng)LogCreated表示是否監(jiān)視新建文件或目錄事件,配置項(xiàng)LogDeleted表示是否監(jiān)視文件或目錄刪除事件,配置項(xiàng)LogRenamed表示是否監(jiān)視文件或目錄重命名事件。而path0,path1,path2等表示監(jiān)視的路徑,支持通配符。系統(tǒng)配置中可以有若干個(gè)path配置項(xiàng)。文件系統(tǒng)監(jiān)視功能設(shè)計(jì)我們可以使用System.IO.FileSystemWatcher來監(jiān)視文件系統(tǒng)的對(duì)象的修改,我們可以使用它的Path屬性來設(shè)置要監(jiān)視的文件夾,使用Filter屬性來設(shè)置文件名過濾器,然后響應(yīng)它的Changed事件來處理文件內(nèi)容修改操作,

21、響應(yīng)Created事件來處理新增文件或目錄操作,響應(yīng)Deleted事件來處理刪除文件或目錄操作,響應(yīng)Renamed事件來處理文件和目錄重命名操作。這這里我們簡單是將這些事件信息保存到數(shù)據(jù)表FileSystemLog中。程序在監(jiān)視文件系統(tǒng)前會(huì)讀取系統(tǒng)配置信息表SystemConfig中讀取配置信息,根據(jù)其中的path配置項(xiàng)目創(chuàng)建若干個(gè)FileSystemWatcher對(duì)象展開監(jiān)視。我們選定服務(wù)的名稱為“MyFileSystemWatcher”。客戶端設(shè)計(jì)本軟件的客戶端具有一個(gè)圖形化用戶界面,其界面設(shè)計(jì)如下客戶端主窗體工具條:刷新 刪除記錄 系統(tǒng)配置 啟動(dòng)服務(wù)

22、0;停止服務(wù)數(shù)據(jù)列表顯示從 FileSystemLog表查詢所得的數(shù)據(jù)狀態(tài)欄此外還有一個(gè)系統(tǒng)配置對(duì)話框,用于查看和修改數(shù)據(jù)表SystemConfig中保存的系統(tǒng)配置信息。軟件說明根據(jù)上述的軟件設(shè)計(jì),我已經(jīng)把軟件編寫完畢,現(xiàn)對(duì)該軟件結(jié)構(gòu)進(jìn)行說明客戶端主界面 frmClient本軟件為一個(gè)C#編寫的EXE,主要包含服務(wù)端軟件模塊和客戶端軟件模塊。首先對(duì)比較好理解的具有圖形化用戶界面的客戶端模塊進(jìn)行說明,客戶端的主界面為 這個(gè)界面主要功能是數(shù)據(jù)庫信息管理,最上面為一個(gè)工具條,中間大部分的一個(gè)ListView控件,最下面為狀態(tài)欄。對(duì)于ListView控件其內(nèi)容是分組的,因

23、此需要設(shè)計(jì)其分組信息,在VS.NET的窗體設(shè)計(jì)器中我們點(diǎn)中ListView控件,在旁邊的屬性列表中選擇Groups屬性,點(diǎn)擊旁邊的小按鈕可以彈出分組設(shè)計(jì)器。 使用這個(gè)分組編輯器我們可以很容易的設(shè)計(jì)該ListView控件的分組信息。這個(gè)窗體的加載事件處理為/ <summary>/ 服務(wù)已經(jīng)安裝標(biāo)記/ </summary>private bool bolServiceInstalled = false  private void frmViewLog_Load(object sender,

24、60;EventArgs e)    try            System.ServiceProcess.ServiceController control = newSystem.ServiceProcess.ServiceController("MyFileSystemWatcher");        System.ServicePro

25、cess.ServiceControllerStatus status = control.Status;        control.Dispose();        bolServiceInstalled = true;        catch( Exception ext )       

26、;     lblServiceInstall.Text = "服務(wù)尚未安裝" ;        myTimer.Enabled = false ;        btnStartService.Enabled = false ;        btnStopService.Enabled =

27、60;false ;        bolServiceInstalled = false ;        MessageBox.Show( this,"服務(wù)尚未安裝:" + ext.Message , "系統(tǒng)錯(cuò)誤");        this.btnRefresh_Click(null,

28、0;null);在這里我們首先創(chuàng)建一個(gè)聯(lián)系到文件監(jiān)視服務(wù)的ServiceController,調(diào)用它的Status屬性,若一切正常則表示服務(wù)已經(jīng)安裝,我們設(shè)置bolServiceInstalled的標(biāo)志變量,若發(fā)生錯(cuò)誤則服務(wù)尚未安裝,則顯示“服務(wù)尚未安裝”的提示信息。 對(duì)于工具條的“刷新列表”按鈕,其點(diǎn)擊事件處理為private void btnRefresh_Click(object sender, EventArgs e)    this.Cursor = System.Windows.Forms.C

29、ursors.WaitCursor;    lvwRecord.BeginUpdate();    try            lvwRecord.Items.Clear();        using (System.Data.IDbCommand cmd = Util.DBConnection.CreateCommand(

30、)                    cmd.CommandText = "Select RecordID , ObjectName , WatchTime , EventStyle From FileSystemLog order by WatchTime"          

31、60; System.Data.IDataReader reader = cmd.ExecuteReader();            while (reader.Read()                          

32、  ListViewItem NewItem = new ListViewItem();                NewItem.Tag = Convert.ToString(reader.GetValue(0);               

33、 NewItem.Text = Convert.ToString(reader.GetValue(1);                NewItem.SubItems.Add(Convert.ToString(reader.GetValue(2);                

34、;string Style = Convert.ToString(reader.GetValue(3);                NewItem.SubItems.Add(Style);                Style = Style.Trim().ToLower();&#

35、160;               if (Style = "created")                             

36、       NewItem.Group = lvwRecord.Groups0;                    NewItem.ImageIndex = 0;               

37、                else if (Style = "changed")                          &

38、#160;         NewItem.Group = lvwRecord.Groups1;                    NewItem.ImageIndex = 1;            &#

39、160;                   else if (Style = "deleted")                       &#

40、160;            NewItem.Group = lvwRecord.Groups2;                    NewItem.ImageIndex = 2;         

41、60;                      else if (Style = "renamed")                    

42、60;               NewItem.Group = lvwRecord.Groups3;                    NewItem.ImageIndex = 3;      

43、0;                         NewItem.StateImageIndex = NewItem.ImageIndex;                lvwRecord.Items.Add(Ne

44、wItem);                        reader.Close();                myStatus.Text = "共列出 " + lvwRecord.Items.Co

45、unt + " 個(gè)記錄"        catch (Exception ext)            MessageBox.Show(ext.ToString(), "系統(tǒng)錯(cuò)誤");        this.Cursor = System.Windows.Forms.Curs

46、ors.Default;    lvwRecord.EndUpdate();在該按鈕事件處理中,我們查詢數(shù)據(jù)表FileSystemLog,對(duì)每一條查詢所得的數(shù)據(jù)創(chuàng)建一個(gè)ListViewItem項(xiàng)目,并根據(jù)記錄的EventStyle值設(shè)置該列表項(xiàng)目的圖標(biāo)序號(hào)和分組狀態(tài)。 工具條的“刪除記錄”按鈕用于刪除列表中選擇的項(xiàng)目,其點(diǎn)擊事件處理為private void btnDelete_Click(object sender, EventArgs e)    if (lvwRecor

47、d.SelectedItems.Count > 0)            using (System.Data.IDbCommand cmd = Util.DBConnection.CreateCommand()                    for (int&#

48、160;iCount = lvwRecord.Items.Count - 1; iCount >= 0; iCount-)                            ListViewItem item = lvwRecord.ItemsiCount;     &

49、#160;          if (item.Selected)                                    cmd.Command

50、Text = "Delete From FileSystemLog Where RecordID = '" + item.Tag + "'"                    cmd.ExecuteNonQuery();         &

51、#160;          lvwRecord.Items.Remove(item);                            /for        /using

52、    在刷新列表中,我們將列表項(xiàng)目的Tag屬性值設(shè)置為數(shù)據(jù)庫記錄的編號(hào),在這里我們利用這個(gè)事先保存的數(shù)據(jù)庫記錄的編號(hào)拼湊出SQL語句然后刪除指定的記錄。 工具條的“啟動(dòng)服務(wù)”按鈕用于啟動(dòng)后臺(tái)的文件監(jiān)視服務(wù)。其點(diǎn)擊事件處理為private void btnStartService_Click(object sender, EventArgs e)    if (bolServiceInstalled = false)    &

53、#160;   return;    using (System.ServiceProcess.ServiceController control = newSystem.ServiceProcess.ServiceController("MyFileSystemWatcher")            if (control.Status = System.ServicePr

54、ocess.ServiceControllerStatus.Stopped)                    control.Start();            在這里我們創(chuàng)建一個(gè)ServiceController對(duì)象,若判斷出服務(wù)的狀態(tài)為停止,則調(diào)用控制器的Start方法來啟動(dòng)服務(wù),在這里Start方法內(nèi)部

55、只是通知操作系統(tǒng)啟動(dòng)指定名稱的服務(wù),它發(fā)送通知后立即返回,并不會(huì)等待服務(wù)啟動(dòng)后返回。類似的對(duì)于“停止服務(wù)”,其點(diǎn)擊事件處理為private void btnStopService_Click(object sender, EventArgs e)    if (bolServiceInstalled = false)        return;    using (System.Ser

56、viceProcess.ServiceController control = newSystem.ServiceProcess.ServiceController("MyFileSystemWatcher")            if (control.Status = System.ServiceProcess.ServiceControllerStatus.Running)     

57、60;              control.Stop();            在這個(gè)處理過程中,若判斷出服務(wù)狀態(tài)為運(yùn)行中,則調(diào)用控制器的Stop方法來停止服務(wù)。在這里Stop方法內(nèi)部只是通知操作系統(tǒng)停止指定的服務(wù),它發(fā)送通知后立即返回,不會(huì)等待服務(wù)停止后返回。我們還在窗體上放置一個(gè)定時(shí)器控件,定時(shí)間隔為2秒,用于根據(jù)服務(wù)的狀態(tài)刷新工具條按鈕狀態(tài),其定時(shí)事件處理為pri

58、vate void myTimer_Tick(object sender, EventArgs e)    if (bolServiceInstalled = false)        return;    using (System.ServiceProcess.ServiceController control = newSystem.ServiceProces

59、s.ServiceController("MyFileSystemWatcher")            btnStartService.Enabled = (control.Status = System.ServiceProcess.ServiceControllerStatus.Stopped);        btnStopService.Enabled = (control.Status = S

60、ystem.ServiceProcess.ServiceControllerStatus.Running);    在這里我們創(chuàng)建了一個(gè)綁定到文件系統(tǒng)監(jiān)控服務(wù)的ServiceController對(duì)象,然后根據(jù)它的Status狀態(tài)來設(shè)置“啟動(dòng)服務(wù)”和“停止服務(wù)”按鈕的可用狀態(tài)。系統(tǒng)配置對(duì)話框 dlgConfig在客戶端主窗體中點(diǎn)擊工具條的“系統(tǒng)配置”按鈕就會(huì)彈出系統(tǒng)設(shè)置對(duì)話框,該對(duì)話框的用戶界面為該對(duì)話框比較簡單,就是用于顯示和修改系統(tǒng)配置信息對(duì)象MyConfig中的內(nèi)容。由于文件系統(tǒng)監(jiān)視服務(wù)只有在啟動(dòng)的時(shí)候讀取系統(tǒng)配置信息,因此對(duì)系統(tǒng)配置的任何修改都需要

61、重新啟動(dòng)服務(wù)才能生效。系統(tǒng)配置信息對(duì)象 MyConfig系統(tǒng)配置信息對(duì)象MyConfig用于讀取和修改保存在數(shù)據(jù)表SystemConfig中的系統(tǒng)配置信息。其包含的配置信息的代碼如下private bool bolLogRenamed = true;/ <summary>/ 是否記錄重命名事件/ </summary>public bool LogRenamed    get  return bolLogRenamed;   

62、;  set bolLogRenamed = value;  private bool bolLogChanged = true;/ <summary>/ 是否記錄文件修改事件/ </summary>public bool LogChanged    get  return bolLogChanged;     set bolLogChanged = value;

63、 private bool bolLogCreated = true;/ <summary>/ 是否記錄對(duì)象創(chuàng)建事件/ </summary>public bool LogCreated    get  return bolLogCreated;     set bolLogCreated = value; private bool bolLogDeleted = true;/

64、0;<summary>/ 是否記錄對(duì)象刪除事件/ </summary>public bool LogDeleted    get  return bolLogDeleted;     set bolLogDeleted = value;  private string myWatchedPaths = null;/ <summary>/ 監(jiān)視的目錄/ </

65、summary>public string WatchedPaths    get  return myWatchedPaths;     set myWatchedPaths = value; 它的Load方法用于從數(shù)據(jù)庫中加載配置信息,其處理過程為public void Load()    myWatchedPaths = null;    System.Collections.ArrayList path

66、s = new System.Collections.ArrayList();    using (System.Data.IDbCommand cmd = Util.DBConnection.CreateCommand()            cmd.CommandText = "Select ConfigName , ConfigValue From SystemConfig"   

67、0;    System.Data.IDataReader reader = cmd.ExecuteReader();        while (reader.Read()                    string Name = Convert.ToString(reader.GetValue(0

68、);            if (Name = null)                            continue;        

69、                Name = Name.Trim().ToLower();            string Value = Convert.ToString(reader.GetValue(1);          &#

70、160; if (Name.StartsWith("path")                            paths.Add(Value.Trim();             

71、0;          else if (Name = "logrenamed")                            bolLogRenamed = Convert.ToBoolean(Va

72、lue);                        else if (Name = "logchanged")                    &#

73、160;       bolLogChanged = Convert.ToBoolean(Value);                        else if (Name = "logdeleted")      

74、;                     bolLogDeleted = Convert.ToBoolean(Value);                       

75、; else if (Name = "logcreated")                            bolLogCreated = Convert.ToBoolean(Value);        &#

76、160;                   myWatchedPaths = (string)paths.ToArray(typeof(string);在該方法中程序查詢數(shù)據(jù)表SystemConfig中的配置項(xiàng)目名稱和數(shù)據(jù),若項(xiàng)目名稱以“path”開頭則為要監(jiān)視的路徑,而配置項(xiàng)logrenamed,logchanged,logdeleted,logcreated分別表示是否監(jiān)視文件目錄重命名,修改,刪除和新建等操作。MyConfig對(duì)象還有一個(gè)

77、Save方法用于將系統(tǒng)配置信息保存到數(shù)據(jù)庫中,其處理過程為public void Save()    using (System.Data.IDbCommand cmd = Util.DBConnection.CreateCommand()            cmd.CommandText = "Delete From SystemConfig"      

78、60; cmd.ExecuteNonQuery();        cmd.CommandText = "Insert Into SystemConfig ( ConfigName , ConfigValue ) Values( ? , ? )" ;        System.Data.IDbDataParameter pName = cmd.CreateParameter();    

79、;    cmd.Parameters.Add( pName );        System.Data.IDbDataParameter pValue = cmd.CreateParameter();        cmd.Parameters.Add( pValue );             

80、;  pName.Value = "LogRenamed"        pValue.Value = bolLogRenamed.ToString();        cmd.ExecuteNonQuery();         pName.Value = "LogChanged"  &

81、#160;     pValue.Value = bolLogChanged.ToString();        cmd.ExecuteNonQuery();         pName.Value = "LogDeleted"        pValue.Value = bolLogDeleted.ToS

82、tring();        cmd.ExecuteNonQuery();         pName.Value = "LogCreated"        pValue.Value = bolLogCreated.ToString();        cmd.Execute

83、NonQuery();         for (int iCount = 0; iCount < myWatchedPaths.Length; iCount+)                    string path = myWatchedPaths iCount ;     

84、;       if( path = null | path.Trim().Length = 0 )                            continue ;        

85、0;               pName.Value = "path" + iCount ;            pValue.Value = path ;            cmd.ExecuteN

86、onQuery();            在這個(gè)方法中,首先刪除數(shù)據(jù)表SystemConfig中所有的記錄,然后將所有的配置信息保存到數(shù)據(jù)表SystemConfig中。文件系統(tǒng)監(jiān)視服務(wù) MyFileSystemWatcherService類MyFileSystemWatcherService就是文件系統(tǒng)監(jiān)視服務(wù),它是從ServiceBase派生的,首先說明一下執(zhí)行文件系統(tǒng)監(jiān)視的功能性的過程,其代碼如下/ <summary>/ 文件系統(tǒng)監(jiān)視器列表/ </su

87、mmary>private System.Collections.ArrayList myWatchers = null; / <summary>/ 開始啟動(dòng)文件系統(tǒng)監(jiān)視/ </summary>/ <returns>操作是否成功</returns>internal bool StartFileSystemWatching()    myWatchers = new System.Collections.ArrayList();  &

88、#160; MyConfig.Instance.Load();    string paths = MyConfig.Instance.WatchedPaths;    System.Text.StringBuilder myPathList = new StringBuilder();    if (paths != null)          

89、;  foreach (string path in paths)                    if (System.IO.Path.IsPathRooted(path) = false)             

90、60;              continue;                        string BasePath = null;      &

91、#160;     string Filter = null;             if (System.IO.Directory.Exists(path)                     

92、0;      BasePath = path;                Filter = "*.*"                      

93、0; else                           BasePath = System.IO.Path.GetDirectoryName(path);             

94、0;  Filter = System.IO.Path.GetFileName(path);                        if (BasePath = null)               

95、             continue;                        BasePath = BasePath.Trim();        

96、0;   if (BasePath.ToUpper().StartsWith(System.Windows.Forms.Application.StartupPath)                            / 不能監(jiān)視程序本身所在的目錄的文件系統(tǒng)更改  

97、0;             continue;                         if (System.IO.Directory.Exists(BasePath) = false)  

98、                          / 不能監(jiān)視不存在的目錄                continue;     &#

99、160;                  if (myPathList.Length > 0)                            myPath

100、List.Append("");                        myPathList.Append(path);            System.IO.FileSystemWatcher watcher = new

101、60;System.IO.FileSystemWatcher();            watcher.Path = BasePath;            watcher.Filter = Filter;            watcher.EnableRais

102、ingEvents = true;            watcher.IncludeSubdirectories = false;            if (MyConfig.Instance.LogChanged)                            watcher.Changed += delegate(object sender, System.IO.FileSystemEventArgs args)             

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論