Series C# hay ho – Tổng quan về Windows Services (WS)

Đây là một bài viết khá hay của bạn Phạm Hồng Sang, bạn cùng lớp ở FPT và đồng nghiệp ASWIG với mình. Bài viết sẽ cho bạn cái nhìn tổng quan về Windows Service, cũng như cách viết một Window Services để xử lý các tác vụ chạy ngầm.

Windows Services là gì?

  • Windows Service có thể hiểu nôm na như là 1 ứng dụng chạy nền trong một khoản thời gian dài từ khi bạn bật máy tính cho đến khi tắt nó đi.
  • Nó có thể tự động chạy khi máy tính được boots lên, có thể restart hay pause mà không cần một sự tác động nào của người dùng tới các công cụ liên quan tới UI.
  • Có thể cài đặt dễ dàng nhờ công cụ hỗ trợ có sẵn của Visual Studio exe thông qua Command Line. Bạn chỉ cần trỏ đúng thư mục có sẵn của file exe và execute nó. Thế là bạn đã cài đặt xong Windows Service.

Tại sao phải sự dụng WS

  • Một trong những yêu cầu quan trọng của khách hàng là: có một ứng dụng chạy ngầm mỗi ngày để tổng hợp data dùng để xuất ra report, đồng bộ data từ các server, xem hôm nay đã có bao nhiêu sản phẩm được bán, hoặc là gửi mail cho các người dùng khi tài khoản của họ đã hết thời gian sử dụng, v…v… 😀
  • Xây dựng 1 WS có thể được xem là 1 giải pháp tối ưu cho những tình huống ở trên mà không cần người dùng thao tác gì tới WS cả, mọi thứ đều được chạy ngầm trên máy tính/server của họ.

Viết một Window Services đơn giản

Với những vấn đề nêu trên, bài viết này mình sẽ hướng dẫn các bạn xây dựng 1 WS từ cơ bản tới nâng cao  từng bước từng bước 1 (đây là những gì mình học được từ dự án thực tế nên muốn share với các bạn :D).

Đầu tiên chúng ta sẽ tạo 1 Project Windows Service như sau.

ClickHere to switch Code GUI

*Note: Vì mình xài VS 2015 nên  trong Windows sẽ có  Universal + Classic Desktop. Còn trong VS 2012-2013 thì ko có nhé :D.

Sau khi tạo xong project, tiếp theo chúng ta sẽ tạo 1 class Utilities để ghi vào file Log những sự kiện xảy ra của WS như sau.

public class Utilities
{
    public static void WriteLogError(Exception ex)
    {
        StreamWriter sw = null;
        try
        {
            sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\LogFile.txt", true);
            sw.WriteLine(DateTime.Now.ToString("g") + ": " + ex.Source + "; " + ex.Message);
            sw.Flush();
            sw.Close();
        }
        catch
        {
            // ignored
        }
    }
    public static void WriteLogError(string message)
    {
        StreamWriter sw = null;
        try
        {
            sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\LogFile.txt", true);
            sw.WriteLine(DateTime.Now.ToString("g") + ": " + message);
            sw.Flush();
            sw.Close();
        }
        catch
        {
            // ignored
        }
    }
}

Tiếp theo chúng ta sẽ trở lại class Service1.cs để bắt đầu implement phần chính của Service. Trong bài mở đầu này, mình sẽ làm những bước cơ bản trước để các bạn hình dung flow của Windows Service trước nhé.

public class Service1
{
    private Timer timer = null;
    public Service1()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        // Tạo 1 timer từ libary System.Timers
        timer = new Timer();
        // Execute mỗi 60s
        timer.Interval = 60000;
        // Những gì xảy ra khi timer đó dc tick
        timer.Elapsed += timer_Tick;
        // Enable timer
        timer.Enabled = true;
        // Ghi vào log file khi services dc start lần đầu tiên
        Utilities.WriteLogError("Test for 1st run WindowsService");
    }
 
    private void timer_Tick(object sender, ElapsedEventArgs args)
    {
        // Xử lý một vài logic ở đây
        Utilities.WriteLogError("Timer has ticked for doing something!!!");
    }
 
    protected override void OnStop()
    {
        // Ghi log lại khi Services đã được stop
        timer.Enabled = true;
        Utilities.WriteLogError("1st WindowsService has been stop");
    }
}

Tới đây thì khá đơn giản để hiểu phải không nào, chúng ta sẽ gọi hàm timer_Tick mỗi 60s để thực hiện 1 business gì đó. Tiếp theo chúng ta trở về UI design của Service1.cs và nhấp chuột phải lên đó để tạo 1 Installer cho WS của mình.
Sau khi tạo xong 1 Installer thì chúng ta sẽ vào properties để cấu hình những thứ cần thiết ví dụ như ServicesNameStartType. Trong ví dụ này mình sẽ chọn mode là Manual để demo, các bạn có thể dùng automatically hay disabled.
Properties On servicesInstaller1Config Properties for services Installer1Sau đó chúng ta sẽ chỉnh thông số cho Process Installer như sau. Vì để demo nên mình sẽ sử dụng máy local để thực thi nên sẽ chọn Account là LocalSystem.

Rightclick services Process Intaller1

config properties for service ProcessInstaller

Các bạn đã viết xong 1 Windows Service rồi đấy. Build project và đọc phần sau để biết cách cài đặt Windows Service nhé các bạn.

Cài đặt Windows Service

Các bạn mở Command line của Visual Studio 2015 như sau : Start -> All Programs -> Visual Studio 2015 -> Visual Studio Tools -> Developer Command Prompt for VS2015. Tới thư mục debug của Project Windows Service.

CD Direct folder

Tại đây chúng ta sẽ dùng lệnh Install, phía sau Install là tên file exe chứa Service nhé:

InstallUtil “FirstWindowsService.exe”

Install Command

Done For Install

Nếu thấy kết quả như trên hình là các bạn đã install thành công rồi đó. Bước cuối cùng là Start Services đó lên và xem file log nhé.

Start Services

File log đã được generate ra trong chính folder chứa service đó. Các event đều đã được log lại trong file .

File Log Created

Log file

Tới đây thì chắc là các bạn đã hiểu cách build một WS như thế nào rồi nhỉ. Để dễ tham khảo Các bạn có thể lấy code của toàn bộ project ở đây: https://github.com/ToiDiCodeDaoSampleCode/WindowService-sample.

Trong phần sau mình sẽ hướng dẫn các bạn sử dụng thư viện Quartz để hẹn giờ cho 1 WS và cũng là những gì mình đi làm mà đúc kết được :D. Hẹn gặp lại các bạn nhé.

11 thoughts on “Series C# hay ho – Tổng quan về Windows Services (WS)”

  1. Trong code demo này ở Sự kiện OnStop(), hình như anh viết sai chỗ Timer.Enabled = true. Thường khi kết thúc Service thì phải dừng Timer chứ anh.

    Like

  2. Thank Hoàng, những bài viết của bạn rất hay và bổ ích với mình. Mình đang có thắc mắc muốn tham khảo bạn và mọi người, mình thấy bây giờ các ứng dùng Client – server đề làm bằng web services hoặc window servicer chứ ko dùng server app có phải vì nó ko còn phù hợp nữa ?

    Like

  3. Mình chạy Command Line nó báo lỗi không cho chạy. Nhưng nếu chạy bằng Run As Administrator thì chạy được. Có cách nào chạy Command Line mà không chạy bằng Run As không vậy ạ.

    Like

  4. Anh có tài liệu nào về quartz không ạ, em muốn làm cái tự động thực thi tác vụ nào đó với thời gian thực hiện hay tắt, bật theo thông tin trong database. quartz em có đọc mà không có ví dụ nên k vào ạ.

    Like

  5. A ơi mình có thể vừa tạo 1 service để đọc dữ liệu và 1 formapplication để config cho nó không ạ ?

    Like

Leave a comment