摘要 本文將向你展示如何用c#開(kāi)發(fā)一個(gè)windows服務(wù)來(lái)記錄系統(tǒng)使用情況。
每一個(gè)人都想知道他們每天在什么時(shí)間啟動(dòng)和關(guān)閉自己的系統(tǒng),以及系統(tǒng)每天運(yùn)行了多少時(shí)間。如果用一個(gè)datagrid控件來(lái)顯示系統(tǒng)啟動(dòng)、關(guān)閉及所消耗的時(shí)間將是一個(gè)不錯(cuò)的主意。
在本文中,我提供了一種方法來(lái)實(shí)現(xiàn)這一目標(biāo)-使用c#開(kāi)發(fā)一個(gè)windows服務(wù)。其實(shí),每個(gè)人都了解一點(diǎn)windows服務(wù)。但是,為了介紹之目的,我僅盡可能少得解釋一下windows服務(wù)。然后,我們來(lái)討論如何設(shè)計(jì)一個(gè)這樣的應(yīng)用程序。
一、 什么是windows服務(wù)?
其實(shí),windows服務(wù)只是運(yùn)行于后臺(tái)的并不要求我們了解的一種進(jìn)程而已。而且,它們的絕大部分并不要求用戶交互。如果我們?cè)?開(kāi)始"菜單的"運(yùn)行"命令行下輸入"services.msc"并回車(chē),那么我們就可以看到在我們當(dāng)前的系統(tǒng)中運(yùn)行的服務(wù)情況。其中,有一些服務(wù)是當(dāng)系統(tǒng)啟動(dòng)時(shí)自動(dòng)啟動(dòng)的。但是,也有一些服務(wù)必須在我們的手工啟動(dòng)下才能運(yùn)行。
二、 windows服務(wù)的優(yōu)點(diǎn)
1. 能夠自動(dòng)運(yùn)行。
2. 不要求用戶交互。
3. 在后臺(tái)運(yùn)行。
一般情況下,windows服務(wù)被用于耗費(fèi)時(shí)間很多的進(jìn)程中,例如備份數(shù)據(jù)庫(kù),等等。
現(xiàn)在,我們要設(shè)計(jì)一個(gè)windows服務(wù)來(lái)實(shí)現(xiàn)記錄你的系統(tǒng)啟動(dòng)和關(guān)閉需要的時(shí)間。我使用visual studio 2003設(shè)計(jì)了這個(gè)應(yīng)用程序。
三、 設(shè)計(jì)windows服務(wù)
第一步:
首先打開(kāi)visual studio并且選擇visual c#工程。選擇模板類(lèi)型為windows服務(wù),并命名為monitoring,如下圖所示:

第二步:
按f7鍵打開(kāi)代碼窗口。然后,加入對(duì)system.io命名空間的引用,以便把系統(tǒng)定時(shí)功能編寫(xiě)到一個(gè)文件中。下一步,用monitoring一詞替換所有出現(xiàn)的service1一詞。之后,轉(zhuǎn)入設(shè)計(jì)模式(按鍵shift+f7)。選擇solution explorer(按鍵ctrl+alt+l)。點(diǎn)擊service1.cs并且命名它為monitoring.cs。
之后,轉(zhuǎn)入代碼窗口。在onstart事件中加入下列代碼,如下圖所示:
在onstart事件中實(shí)現(xiàn)的功能
首先,在c盤(pán)上創(chuàng)建一個(gè)xml文件,并命名為file1。然后,在這個(gè)文件中建立如下代碼:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<times>
然后,關(guān)閉它。
我創(chuàng)建了一個(gè)服務(wù),它能夠在系統(tǒng)啟動(dòng)時(shí)自動(dòng)啟動(dòng)并且記錄下啟動(dòng)時(shí)間。當(dāng)系統(tǒng)關(guān)閉時(shí),它也關(guān)閉。而且,它會(huì)記錄下關(guān)閉時(shí)間和系統(tǒng)中所花費(fèi)的時(shí)間。
首先,我要?jiǎng)?chuàng)建一個(gè)streamwriter來(lái)把系統(tǒng)啟動(dòng)時(shí)間寫(xiě)入file1.xml文件中。
在把代碼復(fù)制到你的onstart事件后,正好在monitoring構(gòu)造器的上面創(chuàng)建一個(gè)公共變量temp,如下圖所示:
此后,把這部分代碼復(fù)制到你的代碼窗口:
再把下面代碼復(fù)制到onstart事件中,如下圖所示:
streamwriter writer=file.appendtext("d://file1.xml");
writer.write("<time>");
writer.writeline("<date> "+ (datetime.now.tostring("dd-mm-yy"))+"</date>");
writer.writeline("<started> "+ (datetime.now.tostring("t"))+"</started>");
temp=datetime.now;
writer.close();
在onshutdown事件中實(shí)現(xiàn)的功能
當(dāng)系統(tǒng)要關(guān)閉時(shí),我使用一個(gè)streamwriter再次打開(kāi)file1.xml-它將記下系統(tǒng)關(guān)閉時(shí)間,還將記下在系統(tǒng)啟動(dòng)和關(guān)閉之間所花費(fèi)的時(shí)間跨度。我在onstart和onshutdown事件中使用了一個(gè)temp變量。在onstart中,它用于存儲(chǔ)啟動(dòng)時(shí)間。然后,它被再次用于onshutdown事件中來(lái)記下系統(tǒng)啟動(dòng)和關(guān)閉之間所花費(fèi)的時(shí)間間隔。
然后,我們必須配置我們的windows服務(wù)以便安裝和運(yùn)行。
因此,首先轉(zhuǎn)到設(shè)計(jì)視圖中,并選擇屬性窗口(可以按下f4)。
把canstop和canshutdown設(shè)置為true。在安裝之前,我們必須要安裝一個(gè)安裝程序。
右擊設(shè)計(jì)視圖窗口,然后選擇"add installer"。然后,它將顯示projectinstaller.cs。在這個(gè)文件中,serviceinstaller1和serviceprocessinstaller1都存在。轉(zhuǎn)到serviceprocessinstaller1屬性處:
· 把a(bǔ)ccount設(shè)置為localsystem。
· 然后,轉(zhuǎn)到serviceinstaller1屬性處。
· 把displayname和servicename設(shè)置為monitoring。
· 設(shè)置啟動(dòng)類(lèi)型(starttype)為automatic。
請(qǐng)參考下圖:
然后,轉(zhuǎn)到vs.net的命令提示符下。
在控制臺(tái)下,轉(zhuǎn)到服務(wù)的debug文件夾下:
輸入"installutil monitoring.exe"
如果它顯示"commit phase completed successfully",則說(shuō)明服務(wù)被成功安裝。
然后,重啟系統(tǒng)以啟動(dòng)服務(wù)。在重啟之后,打開(kāi)file1.xml文件,它記錄了系統(tǒng)的開(kāi)始時(shí)間。如果關(guān)閉系統(tǒng),它將記錄下系統(tǒng)的關(guān)閉時(shí)間和使用系統(tǒng)的時(shí)間長(zhǎng)度。通過(guò)這一部分,我們已經(jīng)完成了記錄下系統(tǒng)所消耗的時(shí)間。接下來(lái),我們將創(chuàng)建一個(gè)web應(yīng)用程序以便在一個(gè)grid控件中顯示xml數(shù)據(jù)。
在下一部分中,我將解釋如何抽取這個(gè)xml文件數(shù)據(jù)并且在一個(gè)datagrid控件中顯示它。 四、 用c#創(chuàng)建一個(gè)web應(yīng)用程序
在這一部分中,我們用c#創(chuàng)建一個(gè)web應(yīng)用程序,并命名為systemmonitor。
加入下面命名空間:
using system.io;
using system.xml;
using system.text;
之后,把datagrid和label控件拖動(dòng)到頁(yè)面上,如下圖所示:

把下列代碼復(fù)制到page_load事件中:
file.copy("c://file1.xml","c://temp1.xml",true);
streamwriter writer1=file.appendtext("c://temp1.xml");
writer1.write("<shutdown>undefined</shutdown>");
writer1.write("<timespent>undefined</timespent>");
writer1.write("</time>");
writer1.writeline("</times>");
writer1.close();
dataset ds=new dataset();
ds.readxml("c://temp1.xml");
timespan t=new timespan();
datagrid1.datasource=ds;
datagrid1.databind();
xmltextreader reader=new xmltextreader("c://temp1.xml");
while(reader.read())
{
if(reader.nodetype==xmlnodetype.element)
{
if(reader.name=="timespent")
{
string temp11=reader.readinnerxml().tostring();
if(temp11!="undefined")
{
temp11=temp11.replace(":",".");
temp11=temp11.replace(" ","");
duration +=convert.todouble(temp11);
}
}
}
}
response.write("total duration is : ");
double temp122=convert.todouble(duration);
string hr=temp122.tostring();
string hrstr=hr.substring(0,hr.indexof("."));
response.write(hrstr.tostring()+" hours");
string mins=hr.substring(hr.indexof(".")+1,(hr.length -hr.indexof(".")-1));
response.write(" "+mins.tostring()+" minutes");
reader.close();
file.delete("c://temp1.xml");
最后把下面的聲明粘貼到page_load事件上部:
private double duration;
我解釋一下程序在page_load事件中做了什么。
首先,我把文件file1.xml(它包含系統(tǒng)定時(shí)信息)的內(nèi)容復(fù)制到臨時(shí)文件中。然后,我把一些標(biāo)記添加到該臨時(shí)文件中。之后,我把temp的內(nèi)容讀取到一個(gè)dataset中,最后把它綁定到一個(gè)datagrid中。以后,我創(chuàng)建邏輯來(lái)查找所有花費(fèi)的時(shí)間。
我非常希望每個(gè)人都能理解上面的代碼。
上面頁(yè)面的輸出結(jié)果大致如下圖所示: