一個Windows後台服務(.Net的C#版) – 定時訪問資料庫迴圈傳送簡訊

來源:互聯網
上載者:User

所謂Windows後台服務,即後台自動啟動並執行程式,一般隨作業系統啟動而啟動,在我的電腦 服務後應用程式 服務裡面能看到當前電腦的服務.一般而言,程式上用VC、C++寫Windows服務,但是我對這些語言不是很熟,一般編程用C#較多,所以就用C#語言寫了一個Windows服務.

其實需求是這樣的,做那個報價系統的時候加入了發簡訊的功能,訂單處理完即將發貨的時候要傳送簡訊都客戶手機上,公司內部員工處理訂單逾時要自動發簡訊,群發產品促銷資訊到客戶手機上等,還有定時傳送簡訊的需求,所以最後面決定把發簡訊的模組獨立出來,以後還有什麼功能方便一起調用,而最終選擇了採用Windows後台服務.

其實Windows服務並不好做到通用,它並不能在使用者的介面顯示一些什麼資訊等,它只是在後台默默的處理一些事情,起著輔助的作用.那如何?發送段信通用調用的介面呢?它們之間的資訊又是如何來互動呢?資料庫!對,就是它儲存資料資訊的.而資料庫都能很方便的訪問操作.把傳送簡訊的後台服務定時去訪問一個資料庫,而另外任何要傳送簡訊的地方也訪問資料庫,並插入一條要發送的簡訊到表裡面,稍後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 });
}

再添加一個服務類繼承自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();
}

執行個體化記時器類啟動後,將在指定時間間隔觸發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();
}

}

上面我們使用try、catch訪問資料庫,並記錄錯誤異常資訊. 傳送簡訊是使用發送一個Web請求發送出去的,要注意請求url字串的編碼類別型,要與請求頁面編碼一致,不然會出現亂碼.上面我們請求的是智網通集團簡訊(網址:http://www.09168.net/)的Web介面,通過訪問他的網站來實現發簡訊,當然還要傳遞一些使用者名稱、密碼、手機號碼和要發送的簡訊息等參數.他的收費平均大概為7分/條的樣子,其實我原本不想用發送Web請求的這樣方式來傳送簡訊的,它本身提供了調用它傳送簡訊的DLL,而且還有vc、delphi調用的Demo,但是沒有用C#調用的例子,我剛開始試著用非託管動態連結程式庫他提供的DLL,不知方法調用那裡出錯了一直都沒能成功發送出簡訊,所以後來就用了他的Web方式介面了.他頁面直接返回傳送簡訊的狀態資訊.返回傳送成功則簡訊發送成功,成功後我再將此條資訊從要傳送簡訊表裡刪除並儲存在發送記錄表裡面,以備日後方便查詢.其實登陸他的官網進入後台也能方便的查詢,如.

傳送簡訊服務的代碼基本上搞定了,就看怎麼在伺服器上安裝部署了.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原創,著作權均歸原作者個人所有,轉載必須保留此段聲明,且在文章頁面明顯位置給出原文串連,否則保留追究法律責任的權利。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.