C#实现Windows后台服务实例浅析
2019獨角獸企業重金招聘Python工程師標準>>>
C#實現Windows后臺服務實例之前要明白的一些概念:所謂Windows后臺服務,即后臺自動運行的程序,一般隨操作系統啟動而啟動,在我的電腦 服務后應用程序 服務里面能看到當前電腦的服務.一般而言,程序上用VC、C++寫Windows服務,但是我對這些語言不是很熟,一般編程用C#較多,所以就用C#語言寫了一個Windows服務.
C#實現Windows后臺服務實例其實需求是這樣的,做那個報價系統的時候加入了發短信的功能,訂單處理完即將發貨的時候要發送短信都客戶手機上,公司內部員工處理訂單超時要自動發短信,群發產品促銷信息到客戶手機上等,還有定時發送短信的需求,所以最后面決定把發短信的模塊獨立出來,以后還有什么功能方便一起調用,而最終選擇了采用Windows后臺服務.
C#實現Windows后臺服務實例其實Windows服務并不好做到通用,它并不能在用戶的界面顯示一些什么信息等,它只是在后臺默默的處理一些事情,起著輔助的作用.那如何實現發送段信通用調用的接口呢?它們之間的信息又是如何來交互呢?數據庫!對,就是它存儲數據信息的.而數據庫都能很方便的訪問操作.把發送短信的后臺服務定時去訪問一個數據庫,而另外任何要發送短信的地方也訪問數據庫,并插入一條要發送的短信到表里面,稍后Windows后臺服務訪問該表將此短信發送出去.這可能是一個比較蠢的方法,但實現起來較簡單.
C#實現Windows后臺服務實例首先,由于它是要安裝的,所以它運行的時候就需要一個安裝類Installer將服務安裝到計算機,新建一個后臺服務安裝類繼承自Installer,安裝初始化的時候是以容器進行安裝的,所以還要建立ServiceProcessInstaller和ServiceInstaller服務信息組件添加到容器安裝,在Installer類增加如下代碼:
private System.ComponentModel.IContainer components = null;? private System.ServiceProcess.ServiceProcessInstaller spInstaller;? private System.ServiceProcess.ServiceInstaller sInstaller;? private void InitializeComponent()? {? components = new System.ComponentModel.Container();?? // 創建ServiceProcessInstaller對象和ServiceInstaller對象? this.spInstaller = new System.ServiceProcess.ServiceProcessInstaller();? this.sInstaller = new System.ServiceProcess.ServiceInstaller();?? // 設定ServiceProcessInstaller對象的帳號、用戶名和密碼等信息? this.spInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem;? this.spInstaller.Username = null;? this.spInstaller.Password = null;?? // 設定服務名稱? this.sInstaller.ServiceName = "SendMessage";? sInstaller.DisplayName = "發送短信服務";? sInstaller.Description = "一個定時發送短信的服務";?? // 設定服務的啟動方式? this.sInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic;?? this.Installers.AddRange(new System.Configuration.Install.Installer[] { this.spInstaller, this.sInstaller });? } C#實現Windows后臺服務實例再添加一個服務類繼承自ServiceBase,我們可以重寫基類的OnStart、OnPause、OnStop、OnContinue等方法來實現我們需要的功能并設置指定一些屬性.由于是定事發送短信的服務,自然少不了Windows記時器,在OnStart事件里我們寫入服務日志,并初始化記時器.
private System.Timers.Timer time;? private static readonly string CurrentPath = Application.StartupPath + "\\";? protected override void OnStart(string[] args)? {? string path = CurrentPath + "Log\\start-stop.log";? FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write);? StreamWriter sw = new StreamWriter(fs);? sw.WriteLine("The Service is Starting On " + DateTime.Now.ToString());? sw.Flush();? sw.Close();? fs.Close();?? time = new System.Timers.Timer(1000 * Convert.ToInt32(GetSettings("TimeSpan")));? time.Enabled = true;? time.Elapsed += this.TimeOut;? time.Start();? } C#實現Windows后臺服務實例實例化記時器類啟動后,將在指定時間間隔觸發Elapsed指定事件,如上GetSettings為讀取我App.config文件里一個配置節點(值為30)的方法,所以上面將會每隔30秒調用TimeOut方法.而改方法就是我們發短信的具體操作.代碼如下:
private void TimeOut(object sender, EventArgs e)? {? try {? if (GetSettings("Enabled").ToLower() == "true")? {? SqlConnection con = new SqlConnection(GetSettings("ConnString"));? SqlCommand cmd = new SqlCommand("select [sysid],[admin_inner_code],[user_inner_code],[phone],[message],[sendtime] from [tbl_note_outbox]", con);? con.Open();? SqlDataReader rdr = cmd.ExecuteReader();? while (rdr.Read())? {? string phone = rdr["phone"].ToString();? string message = rdr["message"].ToString();? string sendtime = rdr["sendtime"].ToString();? System.Text.Encoding encoder = System.Text.Encoding.GetEncoding("GB2312");? string url = string.Format("http://211.155.23.205/isapi.dll?SendSms&AgentID={0}&PassWord={1}&phone={2}&msg={3}&sendtime={4}", GetSettings("AgentID"), GetSettings("PassWord"), phone,System.Web.HttpUtility.UrlEncode( message,encoder), sendtime);? System.Net.WebClient wClient = new System.Net.WebClient();? string msg = System.Text.Encoding.Default.GetString(wClient.DownloadData(url));? wClient.Dispose();?? //刪除已經發送成功的,并保存發送記錄? if (msg == "發送成功")? {? DateTime dtsend = sendtime == "0" ? DateTime.Now : DateTime.ParseExact(sendtime, "yyyyMMddHHmmss", null);? string sql = string.Format("delete from [tbl_note_outbox] where [sysid]={0} INSERT INTO [tbl_note_log] ([admin_inner_code],[user_inner_code],[status],[phone],[message],[sendtime]) VALUES('{1}','{2}','{3}','{4}','{5}','{6}')", rdr["sysid"], rdr["admin_inner_code"], rdr["user_inner_code"], msg, phone, message, dtsend);? SqlConnection conn = new SqlConnection(GetSettings("ConnString"));? SqlCommand delete = new SqlCommand(sql, conn);? conn.Open();? delete.ExecuteNonQuery();? conn.Close();? delete.Dispose();? }?? }? rdr.Close();? con.Close();? cmd.Dispose();? }? }? catch (Exception ex)? {? string errorPath = CurrentPath + "Log\\error.log";? if (!File.Exists(errorPath))? {? FileStream create = File.Create(errorPath);? create.Close();? }? FileStream fs = new FileStream(errorPath, FileMode.Append, FileAccess.Write);? StreamWriter sw = new StreamWriter(fs);? sw.WriteLine("Exception: " +ex.Message+" --"+ DateTime.Now.ToString());? sw.Flush();? sw.Close();? fs.Close();? }?? } C#實現Windows后臺服務實例上面我們使用try、catch訪問數據庫,并記錄錯誤異常信息. 發送短信是使用發送一個Web請求發送出去的,要注意請求url字符串的編碼類型,要與請求頁面編碼一致,不然會出現亂碼.上面我們請求的是智網通集團短信(網址:http://www.09168.net/)的Web接口,通過訪問他的網站來實現發短信,當然還要傳遞一些用戶名、密碼、手機號碼和要發送的短信息等參數.他的收費平均大概為7分/條的樣子,其實我原本不想用發送Web請求的這樣方式來發送短信的,它本身提供了調用它發送短信的DLL,而且還有vc、delphi調用的Demo,但是沒有用C#調用的例子,我剛開始試著用非托管動態鏈接庫他提供的DLL,不知方法調用那里出錯了一直都沒能成功發送出短信,所以后來就用了他的Web方式接口了.他頁面直接返回發送短信的狀態信息.返回發送成功則短信發送成功,成功后我再將此條信息從要發送短信表里刪除并保存在發送記錄表里面,以備日后方便查詢.其實登陸他的官網進入后臺也能方便的查詢,如下圖.
?
C#實現Windows后臺服務實例發送短信服務的代碼基本上搞定了,就看怎么在服務器上安裝部署了.C#寫的Windows后臺服務不能直接安裝,需要借助.NET Framework里面的InstallUtil.exe安裝工具安裝,我們可以做成一個執行CMD命令的文件BAT文件來安裝啟動它,命令如下:
%windir%\Microsoft.NET\? Framework\v2.0.50727\? InstallUtil.exe %CD%\? SendMessage.exe? net start SendMessage?
安裝完成以后,我們可以在我的電腦管理服務里面看到才安裝上的后臺服務.
?
經測試,采用定時訪問數據庫發送短信的服務并不是很耗資源,剛啟動的時候只占用內存為7、8M左右,經過在服務器上連續運行幾天不關閉占用的內存也只升到15M左右,運行比較穩定,這里提供一個短信二次開發接口說明,有興趣的朋友可以去下載看下.
智網動力集團短信二次開發說明文檔示例
特別申明:本文及內容如非特別注明,均為本人Jonllen原創,版權均歸原作者個人所有,轉載必須保留此段聲明源碼天空,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
C#實現Windows后臺服務實例的基本情況就向你介紹到這里,希望對你了解和學習C#實現Windows后臺服務實例有所幫助。
詳細請參考:http://www.codesky.net/article/200908/128303.html
轉載于:https://my.oschina.net/u/582827/blog/228621
總結
以上是生活随笔為你收集整理的C#实现Windows后台服务实例浅析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 改变Linux工作环境中的提示信息
- 下一篇: 【整理】Nginx 战斗准备 —— 优化