創(chuàng)建一個(gè)Windows Service應(yīng)用程序
2024-07-21 02:21:45
供稿:網(wǎng)友
創(chuàng)建一個(gè)windows service應(yīng)用程序
--------------------------------------------------------------------------------
下載本文代碼
見資源
正是由于.net framework的出現(xiàn),才使你能夠構(gòu)建出在系統(tǒng)重新啟動(dòng)時(shí)自動(dòng)運(yùn)行的、無人參與的(unattended)應(yīng)用程序。
by stan schultes
技術(shù)工具箱:vb.net, xml, asp
windows service應(yīng)用程序曾經(jīng)是c++程序員專用的領(lǐng)域,除非你在vb中使用了第三方工具。現(xiàn)在它們則成為system.serviceprocess 命名空間下的.net framework類庫(kù)中的主要部分,你可以隨意使用任何.net語言來構(gòu)建它。windows service是一種系統(tǒng)自動(dòng)的、無人參與的程序(僅存在于windows nt、2000和xp操作系統(tǒng)中),它能夠在系統(tǒng)啟動(dòng)時(shí)開始運(yùn)行。你可以通過service control manager (scm) applet或者一些特殊的service-control應(yīng)用(utility)來訪問windows service。
我將講解如何構(gòu)建一個(gè)用于監(jiān)控文件改變情況的windows service。filechangemonitor service用于隨意地編寫事務(wù)日志(event-log)條目以及當(dāng)文件在一段時(shí)間內(nèi)沒有改變時(shí)發(fā)送e-mail。這種文件監(jiān)控過程在用于確保需要時(shí)進(jìn)行備份、正常運(yùn)轉(zhuǎn)報(bào)告生成器或按時(shí)間表將文件傳送到遠(yuǎn)程系統(tǒng)上時(shí)是非常有用的。filechangemonitor service還能夠發(fā)送顯示程序正常運(yùn)行的綜合報(bào)告。
第一步是構(gòu)建一個(gè)作為將來service項(xiàng)目起始點(diǎn)的windows service程序的模板。打開visual studio.net,用windows service模板來創(chuàng)建一個(gè)新的項(xiàng)目,將其命名為filechangemonitor(點(diǎn)此下載范例代碼)。鼠標(biāo)右鍵單擊solution explorer(se)中的service1.vb文件并將其重新命名為changemonitor.vb。點(diǎn)擊changemonitor 設(shè)計(jì)界面(你會(huì)看到“to add components to your class”消息),并將其在屬性窗口(按f4顯示的窗口)中的的名字和servicename屬性均改為changemonitor。
同樣將屬性窗口中的canpauseandcontinue和canshutdown屬性值設(shè)置為true。 這些屬性控制著該service程序是否能夠暫停/繼續(xù),以及在系統(tǒng)關(guān)閉時(shí)是否做出響應(yīng)。你將在后面使用這些事件(以及stop事件)來保存你的service的“狀態(tài)”――即給定時(shí)間內(nèi)的執(zhí)行文本(execution context )。
接下來,點(diǎn)擊changemonitor 設(shè)計(jì)窗口中的“click here to switch to code view”鏈接。在代碼窗口中,點(diǎn)擊左邊的加號(hào)來打開名為“component designer generated code”的區(qū)域。在sub main過程(routine)中,將servicestorun 賦值語句中的service1改為changemonitor: servicestorun = new system. _
serviceprocess.servicebase() _
{new changemonitor()}
右鍵單擊在se中的filechangemonitor項(xiàng)目,選中屬性,再?gòu)膕tartupobject下拉列表中選擇sub main。現(xiàn)在你就可以開始構(gòu)建你的項(xiàng)目了(通過使用build | build solution菜單項(xiàng))。
創(chuàng)建事件模板和過程
現(xiàn)在,在模板中加入一些事件過程(event-routine)的原型。你等一會(huì)兒可以將代碼添加到這些service事件中去以便處理 windows service程序中的狀態(tài)變化。在代碼窗口中點(diǎn)擊class name combo box(位于代碼窗口上面左側(cè)的combo box),然后選中(overrides)選項(xiàng)。在method name combo box中(位于代碼窗口上面右側(cè)的combo box),依次選中各項(xiàng)以便將過程原型(一個(gè)空程序)添加到代碼窗口中,比如:oncontinue、onpause和onshutdown。你必須在每個(gè)過程中的method name combo box中重新選擇(overrides)選項(xiàng) 。
接下來就開始構(gòu)建過程模板。在你需要添加代碼的changemonitor.vb中創(chuàng)建五個(gè)子過程原型: loadsettings()、savesettings()、runcheck()、runsummary()和startservice()。在這個(gè)類的最頂部imports system.serviceprocess語句的下面,通過使用imports語句來添加其他需要用到的命名空間:imports system.io
imports system.timers
imports system.web.mail
imports system.reflection
imports system.xml.serialization
由于你的service應(yīng)用程序不是一個(gè)web項(xiàng)目,因此你可能需要手動(dòng)將一個(gè)引用(reference)添加到web.mail命名空間下。右鍵單擊se中的filechangemonitor項(xiàng)目,從彈出菜單中選擇add reference。在 add reference對(duì)話框中選擇列表中的system.web.dll條目,單擊select按鈕,然后點(diǎn)ok。
在changemonitor類的頂部、component designer區(qū)域的前面,添加一個(gè)用于文件檢查功能的timer對(duì)象的聲明: private withevents controltimer as timer
然后將下面三行代碼加到onstart和oncontinue事件程序中: startservice()
runcheck()
runsummary()
當(dāng)你的service啟動(dòng)時(shí)會(huì)觸發(fā)onstart事件,而當(dāng)暫停后繼續(xù)運(yùn)行時(shí)則會(huì)觸發(fā)oncontinue事件。
在class name combo box中選擇controltimer,并在method name combo box中選擇elapsed。這樣就會(huì)將controltimer_elapsed事件過程原型添加到項(xiàng)目中了。只需添加這兩個(gè)run語句到controltimer_elapsed事件過程中,然后在onpause、onshutdown和onstop事件過程中添加代碼來中斷計(jì)時(shí)器(timer)并保存設(shè)置: controltimer.stop()
savesettings()
從這個(gè)簡(jiǎn)單的程序大綱中你可以看到用于windows service應(yīng)用程序的文件檢查功能的控制流程是如何運(yùn)作的。當(dāng)其中一個(gè)事件觸發(fā)時(shí),startservice函數(shù)便會(huì)加載設(shè)置,然后運(yùn)行文件和簡(jiǎn)要檢查。你可以在計(jì)時(shí)器時(shí)間到時(shí)運(yùn)行檢查程序;可以用stop或pause事件來中斷計(jì)時(shí)器以及保存設(shè)置。
在startservice過程中添加代碼來創(chuàng)建計(jì)時(shí)器,將時(shí)間間隔定為15秒(以毫秒值計(jì)),然后啟動(dòng)它:controltimer = new timer()
controltimer.interval = 15000
controltimer.autoreset = true
controltimer.start()
autoreset = true屬性設(shè)定使計(jì)時(shí)器在時(shí)間到時(shí)繼續(xù)運(yùn)行。接下來,你可以在check函數(shù)運(yùn)行時(shí)添加代碼來編寫windows application事務(wù)日志,這樣你就可以看到service正在運(yùn)行: private sub runcheck()
eventlog.writeentry(servicename & _
" - check", "checking files.")
end sub
你可以通過windows中的event viewer(ev)應(yīng)用程序來查看事件日志中的消息。
添加一個(gè)安裝程序(installer)
創(chuàng)建service應(yīng)用程序模板的最后一項(xiàng)工作是在項(xiàng)目中添加一個(gè)安裝程序。在它運(yùn)行之前你需要首先注冊(cè)這個(gè)windows service程序。切換到changemonitor設(shè)計(jì)界面并打開屬性窗口(如果看不到的話可以按f4),你可以看到在屬性窗口下面有一個(gè)名為add installer的鏈接,點(diǎn)擊該鏈接后會(huì)出現(xiàn)一個(gè)向?qū)硪龑?dǎo)你將一個(gè)名為projectinstaller的組件添加到當(dāng)前項(xiàng)目中。這個(gè)向?qū)г趐rojectinstaller設(shè)計(jì)界面中放置了兩個(gè)service控件:serviceprocessinstaller和serviceinstaller。
圖1. 設(shè)置service屬性
點(diǎn)擊serviceprocessinstaller控件并對(duì)account屬性進(jìn)行設(shè)置。你可能希望選擇localsystem(大多數(shù)service是運(yùn)行在localsystem中的),但如果你喜歡,你還可以將它設(shè)置為一個(gè)用戶帳戶。點(diǎn)擊serviceinstaller,將它的屬性設(shè)置為displayname = filechangemonitor、 servicename = changemonitor以及starttype = automatic(如果你希望通過手動(dòng)啟動(dòng)該service的話也可以將它設(shè)置為manual)。
通過build | build solution來構(gòu)建你自己的項(xiàng)目,確保不存在什么錯(cuò)誤。現(xiàn)在你就可以使用一個(gè)名為installutil的framework應(yīng)用來安裝你的service了。打開命令行提示(command-prompt)窗口并執(zhí)行corvars.bat文件來設(shè)置環(huán)境變量(你可以下載readme文件來了解詳細(xì)內(nèi)容)。使用cd(change directory)命令將其導(dǎo)航到你項(xiàng)目中的/bin目錄下。執(zhí)行以下命令來安裝你的service:> installutil filechangemonitor.exe
現(xiàn)在你可以使用control panel的administrative tools菜單(win2k 和winxp操作系統(tǒng))中的scm applet來啟動(dòng)、停止、暫停以及繼續(xù)運(yùn)行你的filechangemonitor service了 (見圖1)。當(dāng)你啟動(dòng)這個(gè)service后就可以使用ev來查看application事務(wù)日志中由該service生成的事件了。點(diǎn)擊f5刷新ev的顯示,你會(huì)看到“check messages every 15 seconds”。你可以使用以下命令來卸載這個(gè)service(先用scm來終止service): > installutil filechangemonitor.exe /u
現(xiàn)在你可以保存該項(xiàng)目并將它作為以后service程序的一個(gè)模板。
service以某種狀態(tài)運(yùn)行(這可能是它未運(yùn)行時(shí)保存的一組設(shè)定)。當(dāng)service重新啟動(dòng)時(shí),你可以加載它上次運(yùn)行時(shí)的狀態(tài)。一個(gè)簡(jiǎn)便的方法是使用.net framework中的序列化類(serialization class),如system.xml.serialization命名空間下的xml序列化(你也可以選擇binary和soap序列化)。
用xml序列化保存設(shè)置
xml序列化是和用<serializable()>屬性標(biāo)記的類配合使用的。右鍵單擊se中的filechangemonitor項(xiàng)目,從彈出的菜單中選擇add | add class,將該類命名為cmonitor并點(diǎn)擊 ok。在cmonitor中添加兩個(gè)類――monitorheader和monitorfile: <serializable()> public class monitorheader
public monitorintsecs as integer
'<other header properties>
public files() as monitorfile
end class
<serializable()> public class monitorfile
public path as string
'<other file properties>
end class
monitorheader包含控制service的設(shè)置,包括一組monitorfile對(duì)象。monitorfile對(duì)象中包含每個(gè)你想要檢查進(jìn)度的文件的監(jiān)控設(shè)置。你可以將大多數(shù)類的屬性當(dāng)作public變量來實(shí)現(xiàn),因?yàn)樗鼈冎挥糜谀愕膕ervice項(xiàng)目中。查看范例代碼來了解該類的完整定義。你可以在changemonitor 類的模塊中實(shí)現(xiàn)loadsettings和savesettings序列化過程(見列表1)。
在用于聲明設(shè)置對(duì)象和存儲(chǔ)設(shè)置文件路徑的changemonitor類的頂部添加該類的私有變量:private m_monitorcontrol as new _
monitorheader()
private m_ssettingspath as string
在調(diào)用startservice()之前將代碼添加到onstart過程中,來完成在service啟動(dòng)之前對(duì)設(shè)置文件名進(jìn)行檢測(cè)。用reflection來找到應(yīng)用程序的runtime .exe路徑,并用substitute .xml作為文件的擴(kuò)展名(這兩個(gè)文件在同一目錄下): m_ssettingspath = [assembly]. _
getentryassembly.location. _
replace(".exe", ".xml")
在vb.net中assembly是一個(gè)關(guān)鍵字,因此在代碼中你必須把它用一個(gè)方括號(hào)括起來。你需要整理startservice()過程以便從設(shè)置文件中加載計(jì)時(shí)器間隔: if m_monitorcontrol _
.monitorintervalsecs > 0 then
controltimer.interval = _
ctype(m_monitorcontrol _
.monitorintervalsecs * 1000, double)
controltimer.autoreset = true
controltimer.start()
end if
現(xiàn)在,你可以實(shí)現(xiàn)主要的檢查函數(shù)――runcheck了(見列表2)。runcheck負(fù)責(zé)調(diào)用runalarmaction并計(jì)算出files數(shù)組中每個(gè)文件的出現(xiàn)次數(shù),該文件的nextcheck代表的是當(dāng)前時(shí)間之前的時(shí)間并且自從上次檢查以后就沒有發(fā)生過改變。runalarmaction負(fù)責(zé)檢查alarmaction標(biāo)記、編寫事務(wù)日志,然后通過sendemail過程來發(fā)送e-mail (見列表3)。
你可以采用類似的方法,基于monitorheader結(jié)構(gòu)的匯總設(shè)置(summary setting)來實(shí)現(xiàn)runsummary和runsummaryaction方法,構(gòu)建并測(cè)試你的windows service應(yīng)用程序。范例代碼中還包括一個(gè)名為filechgctl的service-control應(yīng)用。它主要用于調(diào)試目的,可以將自定義命令(custom command)發(fā)送到filechangemonitor service中。自定義命令是一個(gè)范圍在128到255之間的整數(shù)。當(dāng)windows service應(yīng)用程序中的oncustomcommand事件觸發(fā)時(shí)你會(huì)得到自定義命令出現(xiàn)的通知。
你會(huì)發(fā)現(xiàn)service 應(yīng)用程序在很多情況下是非常有用的,比如用在系統(tǒng)維護(hù)、監(jiān)控以及其他自動(dòng)的、無人照顧的操作中。windows service通常會(huì)通過事務(wù)日志來記錄其活動(dòng)情況,但正如我所介紹的,你的service也可以通過發(fā)送e-mail來方便地跟蹤其進(jìn)展情況。構(gòu)建windows service應(yīng)用程序的能力使你在用windows構(gòu)建有效的商務(wù)方案方面得以輕松地?cái)U(kuò)展。
關(guān)于作者:
stan schultes 是florida州sarasota地區(qū)的一名web和企業(yè)應(yīng)用程序的架構(gòu)師和開發(fā)人員,以及vb開發(fā)領(lǐng)域的mcp。stan是vsm的一名特約編輯,定期為該雜志撰寫文章。你可以訪問stan的網(wǎng)站www.vbnetexpert.com查看在線代碼演示、更新資料以及其他信息。他的e-mail地址是[email protected]。