所以我朋友每天早上就很認命來公司產生完報表,匯出成Excel檔,然後加密,寄信給老闆。
即使生病請假或是想出去玩請假,還是得連到公司電腦,繼續上面的步驟。
便想到如何每天自動產生報表,然後自動加密,然後寄信。
所以就來試寫看看啦。
分析需求:
- 首先因為是常駐程式,總不能一直開著。程式的定位就是視窗服務 ( windows service )。
- 然後有用到寄信服務,也就是需要 SMTP 服務,所以建議 windows server 的環境。
- 因為有需要產出報表,需要有 reporting service (廢話) 。
1.首先設定 SMTP 的服務,如果有問題可參考這篇,然後進行下一步。筆者用另外已經按裝好的win 2003 伺服器來使用。
static string strFile = @"C:\ReportUse\report.xls" ;
5.撰寫下載 Report 程式碼 GetRPFile。
/// <summary>
/// 取得檔案
/// </summary>
protected void GetRPFile()
{
//網址部分
Uri uri = new Uri(@"http://localhost/ReportServer?/RPReport&TitleName=ReportName&rs:Format=Excel");
//利用Webclient來提供驗服務
WebClient webClient = new WebClient();
//驗證帳號密碼
System.Net.NetworkCredential myCr = new NetworkCredential("帳號", "密碼");
webClient.Credentials = myCr;
//下載檔案到目的位址,目前設定為C:\ReportUse
webClient.DownloadFile(uri, strFile);
}
6.因為要替下載下來的Excel檔進行加密動作,需要制方案總管的專案點選右鍵,選擇[加入參考...]
7.點選上方頁籤 [.NET] 後選擇 [Microsoft.Office.Interop.Excel] 。
8.撰寫Excel加密相關程式碼 AddPasscode。
/// <summary>
/// 替Excel報表加入密碼
/// </summary>
/// <param name="password">密碼</param>
protected void AddPassword(string password)
{
//開啟目標Excel報表
Application objExcel = new Application();
Workbook objWorkBook = objExcel.Workbooks.Open(strFile);
//加入密碼
objWorkBook.Password = password;
//存檔
objWorkBook.Save();
objExcel.Quit();
}
9.撰寫一個寄信的相關類別 SendMail。
/// <summary>
/// 寄信程式
/// </summary>
/// <param name="objMail">信件地址</param>
/// <param name="intBadMailCount">重試次數</param>
/// <returns></returns>
/// <remarks></remarks>
protected bool SendMail(MailMessage objMail, int intBadMailCount = 0)
{
bool IsSuccess = true;
SmtpClient objSMTP = new SmtpClient();
//使用網路SMTP發送MAIL
//objSMTP.DeliveryMethod = SmtpDeliveryMethod.Network
//objSMTP.Host = "主機位置"
//objSMTP.Credentials = New Net.NetworkCredential("帳號", "密碼")
//使用IIS內建SMTP發送MAIL
objSMTP.DeliveryMethod = SmtpDeliveryMethod.PickupDirectoryFromIis;
objSMTP.Host = "Localhost";
objSMTP.Port = 25;
bool IsCircle = true;
int intCount = 0;
while (IsCircle)
{
try
{
objSMTP.Send(objMail);
IsSuccess = true;
IsCircle = false;
}
catch (SmtpFailedRecipientsException ex)
{
//針對發送失敗的使用者紀錄
for (int i = 0; i <= ex.InnerExceptions.Length; i++)
{
SmtpStatusCode status = ex.InnerExceptions[i].StatusCode;
if (status == SmtpStatusCode.MailboxBusy || status == SmtpStatusCode.MailboxUnavailable)
{
Console.WriteLine("信箱忙碌中");
}
else
{
Console.WriteLine("無法傳送至該信箱因{0} ", ex.InnerExceptions[i].FailedRecipient);
}
}
IsCircle = true;
IsSuccess = false;
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in RetryIfBusy(): {0}", ex.ToString());
IsCircle = true;
IsSuccess = false;
}
finally
{
//每發送失敗
if (IsCircle)
intCount += 1;
if (intCount >= intBadMailCount)
IsCircle = false;
}
}
objSMTP = null;
return IsSuccess;
}
10.首先撰寫一個要觸發的事件 chkProcess 準備讓服務來每小時觸發一次。
protected void chkProcess(object source, ElapsedEventArgs e)
{
DateTime dtNow = DateTime.Now;
//依照時間點進行工作
//7點進行取得檔案
if (dtNow.Hour == 7)
{
GetRPFile();
}
//8點加入密碼
else if (dtNow.Hour == 8)
{
AddPassword("Password");
}
//9點寄信
else if (dtNow.Hour == 9)
{
MailMessage objMail = new MailMessage(new MailAddress(@"system@yahoo.com.tw", "報表系統管理者"), new MailAddress(@"user@yahoo.com.tw", "收件者"));
objMail.Subject = dtNow.ToString("yyyy-MM-dd")+ "報表寄送";
objMail.Body = "今天報表如附件,謝謝您。";
objMail.Attachments.Add(new Attachment(strFile));
SendMail(objMail,2);
}
}
11.設定一個 timer 固定每一個小時觸發一次。
static System.Timers.Timer objTimer;
protected override void OnStart(string[] args)
{
//設定每一小時執行一次
objTimer.Interval = 3600000;
objTimer.Enabled = true;
objTimer.Elapsed += new ElapsedEventHandler(chkProcess);
Console.ReadLine();
//因需要長時間觸發,所以要設定GC避免回收資源
GC.KeepAlive(objTimer);
}
12.再設定停止服務時將 timer 關閉並回收。
protected override void OnStop()
{
// 在此加入停止服務所需執行的終止程式碼。
// 清掉計時器
objTimer.Enabled = false;
objTimer.Close();
objTimer.Dispose();
objTimer = null;
}
13.切換至設計界面,往空白部分右鍵點選 [加入安裝程式]。
14.接著修改自動產生的兩個控制項的相關參數。
15.設定 serviceInstaller1 的顯示名稱 (DisplayName)、描述 (Description)、服務名稱 (ServiceName)、啟動類型 (StartType)。
16.以及設定 serviceProcessInstaller1 的啟動帳戶 (Account),設定完這些就差不多大功告成了。
17.將專案編譯之後,該專案所編譯出來的組件 (Assembly) 就具有「安裝能力」,只要透過 NET 提供的安裝程式工具 (Installutil.exe) 便可以將該服務順利安裝至系統內。
C:\WINDOWS\Microsoft.NET\Framework\framework版本\InstallUtil.exe testSendReportByMail.exe
19.而解除按裝相關指令
C:\WINDOWS\Microsoft.NET\Framework\framework版本\InstallUtil.exe /u testSendReportByMail.exe
20.如果沒問題,之後便可以收到 Mail 。
最後因為需要釐清的觀念很多,例如如何使用 Windows Service 以及如何利用 SMTP 發送 Mail 等概念需要事先研讀一陣子。
然後 Windows Service 也比較不易除錯,要事先注意一下。
Windows Service 新增 Installer 功能並自動開啟防火牆設定
SmtpException.StatusCode 屬性
沒有留言:
張貼留言