Cập nhật tự động chương trình
I. Đặt vấn đề:
Tự động update chương trình là một tính năng không thể thiếu đối với 1 phần mềm chuyên nghiệp. Bởi vì:
- 1. Dù bạn có cẩn thận đến đâu, việc chương trình mắc lỗi là khó tránh khỏi. Bạn cần phải đưa ra các bản vá lỗi để sửa chữa các sai lầm đó
- 2. Theo thời gian các quy định, luật của nhà nước, của các đối tác với bạn có thay đổi. Chương trình của bạn cần phải sửa để hoạt động đúng luật của nhà nước, đúng quy định của đối tác
- 3. Theo thời gian, các tính năng cần phải liên tục được sửa đổi, nâng cấp để tạo ra sự tiện dụng cho khách hàng
- 4. Còn hàng tá các lý do khác nữa mà bạn không thể không cập nhật chương trình của mình
II. Các yêu cầu cần có:
Để làm chương trình của bạn tự động cập nhật được, bạn bắt buộc phải có 1 máy chủ web. Đây sẽ là nơi chứa các bản update của bạn. Bạn có thể sử dụng máy chủ riêng, hoặc host + domain thuê cũng được nhưng nên tính đến khả năng thuê dài hạn. Nếu một ngày host thuê của bạn hết hạn, các chương trình sẽ không biết phải cập nhật phiên bản từ đâu.
III. Bắt đầu làm cập nhật:
(Lưu ý các bạn là mình đang hướng dẫn các bạn làm trên .NET. Các ngôn ngữ khác mình sẽ không bàn ở đây)
Có thể có rất nhiều cách cập nhật chương trình, nhưng hiện tại mình mới biết sử dụng 3 cách. Mình tạm thời phân chia 3 cách đó theo nguyên lý hoạt động của chúng như sau (Đây là cách phân chia theo chủ quan của mình)
- 1. Cập nhật tự động: vâng, cách này thực sự là tự động theo đúng nghĩa của nó. Trong chương trình của bạn sẽ không cần 1 chút code nào để kiểm tra xem khi nào thì có phiên bản mới, tải phiên bản mới về như thế nào, cài nó lên máy khách như thế nào. Tất cả việc bạn cần làm là code cho tốt phần xử lý chính của chương trình, dịch nó, và đưa nó lên mạng. Microsoft sẽ thay bạn làm tất cả phần cập nhật. Trước kia Google Chrome cũng đã làm theo cách này. Bây giờ thì hình như nó đã bỏ rồi, tuy nhiên nếu bạn vẫn muốn sử dụng nó thì cũng vẫn chưa muộn. Công nghệ này thực sự là vẫn chưa lỗi thời, vì rằng Visual Studio 2012 vẫn còn hỗ trợ nó khá tốt.
- + Ưu điểm: thực hiện nhanh và đơn giản. Đỡ phải đau đầu vì mấy cái vụ update, giúp bạn dành nhiều thời gian hơn cho chương trình chính
- + Nhược điểm:
- - mỗi lần bạn cho ra lò phiên bản mới, toàn bộ các file (kể cả các file chả có thay đổi gì) sẽ được đưa lên máy chủ web và lại được tải toàn bộ về ở phía khách hàng. Sẽ tốn kha khá thời gian cho việc tải lên và tải về. Vì vậy cách này không nên áp dụng cho các chương trình có dung lượng file lớn
- - Chương trình làm theo kiểu này sẽ không được cài đặt vào Program Files như đa số các chương trình khác mà bạn thấy. Thay vào đó nó sẽ nằm trong một thư mục ở C:\Users\<tên user> (đối với Win7 trở lên) và trong C:\Documents And Settings\<tên user> đối với WinXP. Điều này có thể sẽ gây khó chịu chút ít cho bạn nếu muốn mở thư mục làm việc của bạn ra (ở trên máy khách) và tìm tòi 1 số thứ như: nhật ký lỗi, chỉnh sửa chuỗi connection, chỉnh sửa setting gì đó trong app.config... Tuy nhiên, nếu bạn làm tốt chương trình của mình thì sẽ chả bao giờ bạn cần phải quan tâm xem chương trình sẽ được cài đặt ở đâu trên máy khách.
- - Cách này sẽ bị hạn chế nếu bạn làm với 1 số công cụ đã Cr*ck (cụ thể là mình đã từng bị lỗi với bộ công cụ DevXpress). Tuy nhiên, việc cr*ck các bộ công cụ để sử dụng là việc làm sai trái nên đây chưa thực sự là một hạn chế đáng kể của cách Update này.
- 2. Cập nhật bán tự động: Là chương trình của bạn phải tự kiểm tra xem khi nào thì có phiên bản mới. Nếu có phiên bản mới thì tải nguyên cái file cài đặt (file đã đóng gói cho chương trình của bạn) về máy và chạy nó lên. Còn việc gỡ chương trình cũ ra khỏi máy và cài chương trình mới vào như thế nào thì nguyên cái file đóng gói đó nó đã giúp bạn rồi. Như vậy khoảng 1 nửa công đoạn trong quá trình Update sẽ do bạn tự quản lý (tuy nhiên cũng có 1 số công cụ hỗ trợ giúp cho việc này của bạn đỡ vất vả đi nhiều). Đây là cách mà tôi hay sử dụng. Nó không quá khó và cũng không bị hạn chế nhiều như cách trên. Bạn có thể thấy Notepad++ cũng đang sử dụng cách này.
- + Ưu điểm:
- - Chương trình được cài vào Program Files, cấu trúc thư mục rõ ràng, dễ cho bạn tìm lại nếu chẳng may cần sửa trực tiếp cái gì đó
- - Không bị hạn chế với các công cụ phi pháp mặc dù mình không khuyến khích các bạn sử dụng phi pháp các công cụ của người ta
- + Nhược điểm:
- - Phiên bản mới vẫn có dung lượng lớn vì nó vẫn chứa tất cả các file liên quan đến chương trình của bạn
- - Mỗi lần có phiên bản mới là khách hàng lại phải chạy qua 1 lần quá trình Setup
- 3. Cập nhật thủ công: Có thể có bạn sẽ thắc mắc: đã cập nhật tự động rồi lại còn thủ công nữa là sao? Vâng, mình xin giải thích thủ công ở đây là thủ công đối với bạn(vì bạn phải làm mọi thứ) còn với khách hàng thì nó vẫn là tự động vì chương trình của bạn đã làm thay họ rồi. Với cách này, bạn sẽ phải làm tất cả từ việc kiểm tra xem khi nào thì có bản mới, khi nào thì cần tải nó về, tải như thế nào và cập nhật vào máy khách hàng như thế nào. Cách này sẽ khá vất vả cho bạn, bù lại chương trình chỉ tải về các file cần thiết (các file đã có thay đổi) vì thế tiến trình cập nhật sẽ nhanh hơn, đỡ tiêu tốn tài nguyên, thời gian, và không cần khách hàng phải chạy lại chương trình Setup.
Mình đã đưa ra 3 phương pháp hiện tại mình đang biết cùng với ưu, nhược điểm của từng phương pháp. Chọn cách nào cho chương trình của bạn là tùy thuộc vào bạn, hoặc giả bạn có phương pháp khác thì có thể chia sẻ cùng mọi người. Sau đây mình sẽ lần lượt hướng dẫn làm theo từng phương pháp một. Vì bài viết này khá dài nên có thể sẽ không thể hoàn thành ngay 1 lúc được, mong các bạn thông cảm.
Kỳ I: Update tự động
Trong bài viết hôm nay, tôi sẽ hướng dẫn các bạn tạo chương trình cập nhật tự động bằng ClickOne. ClickOne cho phép bạn tạo cả bộ cài đặt lẫn tính năng Update tự động rất nhanh và hiệu quả.
A. Chuẩn bị
+ Project: Tôi đã chuẩn bị sẵn 1 Project như sau: tên project là AutoUpdateTut1
Vâng, 1 Project rất đơn giản, chỉ có 1 Form trắng, không thêm control nào khác, không code xử lý. Tôi sẽ đóng gói Project này và thêm tính năng tự động cập nhật. Ở lần chạy cập nhật tiếp theo, tôi sẽ bổ sung 1 Button vào trên Form để các bạn thấy các thay đổi đã diễn ra như thế nào.
+ Website để đưa chương trình lên: giả sử tôi có 1 Website ở địa chỉ http://your-website.com. Khách hàng khi muốn tải phần mềm của tôi về sử dụng sẽ được cấp đường link tải phần mềm về tại địa chỉ: http://your-website.com/software/AutoUpdateTut1
+ Tài khoản FTP để truyền file lên WebServer: có nhiều cách để đưa các file phần mềm của bạn lên Web nhưng tôi thấy cách thông dụng nhất là sử dụng FTP. ClickOne cũng hỗ trợ rất tốt FTP (nó dịch file và truyền thẳng lên máy chủ thông qua FTP). Nếu sử dụng cách này, bạn chỉ cần khai báo địa chỉ FTP 1 lần là chạy xả láng luôn. Vì vậy bạn hãy chuẩn bị 1 tài khoản FTP có quyền đoc/ghi file lên máy chủ web. Ở đây tôi chuẩn bị 1 tài khoản ví dụ là ftpuser1, có quyền đọc/ghi file từ thư mục gốc của website.
B. Thực hiện
+ Từ Visual Studio, Click chuột phải vào Project chính của bạn và chọn mục Publish
+ Trên cửa sổ Publish Wizard mới hiện ra, nhập địa chỉ FTP đến vị trị đặt phần mềm trên máy chủ Web, sau đó nhấn Next
+ Bước tiếp theo, bạn nhập vào địa chỉ web mà bạn dự định cấp cho khách hàng để tải phần mềm về (đây cũng chính là địa chỉ mà phần mềm của bạn sẽ kiểm tra phiên bản mới)
+ Bước tiếp theo, bạn chọn chế độ làm việc cho chương trình của bạn là Online hay Offline. Ở chế độ Online only (chế độ thứ 2 trong hình dưới đây), mỗi lần bạn chạy chương trình thì các tệp tin cần thiết để chạy sẽ được tải về máy. Chế độ này cần phải có kết nối mạng internet thì mới khởi động được chương trình. Ở chế độ Online or Offline (chế độ thứ nhất trong hình dưới), ứng dụng của bạn sẽ được tải về máy 1 lần. Ở các lần sau, nếu không có mạng internet thì nó cứ chạy với phiên bản đã tải về. Nếu có mạng Internet, chương trình sẽ tự động kiểm tra xem trên website có bản nào mới hơn không. Nếu có bản mới hơn, nó sẽ tải bản mới về và chạy với bản mới. Như vậy, dù bạn chọn chế độ Online hay Offline thì chương trình của bạn cũng sẽ được cập nhật phiên bản mới nhất
+ Cuối cùng, bạn nhấn vào nút Finish, Visual Studio sẽ hỏi bạn tên đăng nhập và mật khẩu để truyền file qua FTP. Bạn nhập vào tên đăng nhập và mật khẩu đã chuẩn bị ở bước A, sau đó nhấn OK
+ Bạn cần đợi 1 khoảng thời gian nhất định (tùy thuộc vào dung lượng các file bạn cần đưa lên lớn hay nhỏ và đường truyền từ máy bạn lên website) để Visual Studio đưa các file lên máy chủ Web. Sau khi việc tải file lên hoàn tất, trang web chứa liên kết để cài đặt ứng dụng của bạn sẽ được tự động mở ra
+ Bạn Click vào nút Install để tải file setup.exe về, chạy file này để tiến hành cài đặt
+ Quá trình cài đặt kết thúc, ứng dụng của bạn sẽ tự động chạy lên.
Rất đơn giản phải không các bạn? Nhìn qua quy trình thì có vẻ dài dòng, nhiều bước nhưng thực ra nếu bạn đã làm quen rồi thì chỉ cần vài cái click chuột là đã hoàn thành. Không cần thêm bất cứ 1 dòng Code nào. 1 mũi tên lại trúng tới 2 cái đích (vừa đóng gói được ứng dụng, vừa có tính năng tự động cập nhật).
Chương trình của bạn bây giờ sẽ nằm ở trong 1 thư mục đại khái là như thế này: C:\Users\<tên user>\AppData\Local\Apps\2.0\GEC6951W.K73\VGQ082ZX.OK1\auto..tion_faacdffd77271a05_0001.0000_e4a74cb751ea8fbe, trong đó <tên user> là tên tài khoản Windows của bạn. Còn các thư mục có ký hiệu loằng ngoằng kia thì trên mỗi máy sẽ khác nhau, nhưng điều đó không thực sự quá quan trọng. Chỉ cần trong chương trình của bạn xử lý tốt thì file chạy nằm ở đâu cũng không phải là vấn đề quá lớn.
C. Một số lưu ý:
+ Ở bước cài đặt ứng dụng, khi bạn Click vào nút Install trên website, có thể bạn sẽ nhận được 1 cái thông báo lỗi 404 (không tìm thấy file). Điều này thỉnh thoảng hay xảy ra nếu website của bạn host trên IIS6. Nguyên nhân của nó là do IIS6 mặc định không cho tải tệp tin EXE về. Để khắc phục, bạn có thể làm như sau:
- - Mở IIS Manager (trên máy chủ web ra) - nếu bạn không có quyền truy cập vào máy chủ web thì phải yêu cầu admin làm giúp bạn thôi
- - Right Click vào website của bạn và chọn Properties
- - Chuyển sang Tab "Home Directory"
- - Trong mục Execute Permission, chọn Script only
- - Nhấn OK để lưu lại và bạn có thể tải file cài đặt bình thường
Đây hoàn toàn không phải là một lỗi của phương pháp đóng gói phần mềm và tự động cập nhật ClickOne mà bản thân nó đến từ việc thiết lập website chưa đúng.
+ Trên máy tính cài Win7 hoặc Win8, bạn có thể sẽ gặp 1 số thông báo về quyền cài đặt phần mềm lên máy tính. Đây là cảnh báo hết sức bình thường khi bạn cài phần mềm lên máy tính.
D. Tùy chọn nâng cao
Có 1 số tùy chọn khi sử dụng ClickOne, bạn có thể tham khảo thêm để cho ứng dụng của bạn linh hoạt hơn. Để vào mục tùy chọn, Trong Visual Studio bạn Right Click vào Project chính của mình, chọn Properties. Ở Tab Publish, bạn có thể có 1 số tùy chọn như sau:
- + Automatic increment revision with each publish: Tự động tăng số hiệu phiên bản của bạn lên mỗi lần Publish. Số hiệu phiên bản chỉ tự động tăng ở phần Revision. Nếu số hiệu phiên bản có thay đổi thì chương trình phía client mới nhận ra đã có phiên bản mới để Update. Bạn có thể để tự động tăng hoặc bỏ dấu tích đi và điền vào số phiên bản mà bạn muốn
- + Application Files: sẽ mở ra hộp thoại cho phép bạn chọn các file đi kèm ứng dụng của mình
- + Prerequisites: sẽ mở ra hộp thoại cho phép bạn chọn các phần mềm cần có để chạy ứng dụng. Chương trình này làm trên .NET nên mặc định nó đã chọn .NET cho bạn rồi. Nếu cần thêm chương trình gì phụ trợ nữa thì bạn có thể chọn thêm
- Updates: Chọn chế độ tự động Update cho chương trình. Có 2 chế độ là kiểm tra Update trước khi chạy chương trình và kiểm tra update khi thoát chương trình
- Options: thêm 1 số tùy chọn khác cho bạn như: có đặt Shortcut cho chương trình của bạn ra Desktop không, có đăng ký file extension với máy khách không.... cái này các bạn tự tìm hiểu thêm nhé
E. Kiểm tra cập nhật
+ Bây giờ tôi sẽ tạo ra 1 thay đổi trên chương trình AutoUpdateTut1 bằng cách thêm 1 Button trên Form chính.
+ Đóng gói lại chương trình bằng cách Right Click vào project AutoUpdateTut1 và chọn Publish
+ Cửa sổ Publish hiện ra, bây giờ chỉ cần nhấn Finish (vì các thông số đã khai báo cả rồi)
+ Nhập Username và Password FTP khi được hỏi, vậy là hoàn tất bước cập nhật
+ Chạy lại chương trình lúc trước và bạn sẽ thấy các thay đổi đã được cập nhật
Kỳ II: Update bán tự động
Như đã nói ở bài giới thiệu, update bán tự động theo phân loại của mình là việc bạn tự kiểm tra phiên bản của chương trình, tải file setup mới về nếu phiên bản có thay đổi và chạy file Setup lên. Quá trình gỡ phiên bản cũ đi và cài phiên bản mới vào máy khách sẽ do file Setup của bạn làm giúp bạn.
Nguyên tắc kiểm tra phiên bản mới là như thế này:
+ Bạn đặt một file text, xml trên máy chủ web. Trong file đó bạn có ghi thông tin về phiên bản mới nhất, địa chỉ web để tải phiên bản mới về...
+ Chương trình của bạn cần làm mỗi khi check update là lấy nội dung file thông tin đó về, so sánh phiên bản nhận được (từ nội dung file) với phiên bản hiện tại đang chạy. Nếu phiên bản đang chạy đã cũ thì:
- - tải file setup (theo đường dẫn đã lấy được từ file thông tin) về 1 thư mục tạm của máy
- - sử dụng Process.Start để chạy file setup đó
- - thoát khỏi chương trình đang chạy
Trong phần hướng dẫn này, bạn cần sử dụng 1 số kỹ thuật:
- + Tải 1 file từ web về máy
- + Sử dụng Process.Start để chạy file setup
Về kỹ thuật đóng gói chương trình, tôi sẽ hướng dẫn ngay sau đây, còn 2 kỹ thuật tải file và chạy file với Process.Start thì tôi sẽ mô tả trong kỳ III, bởi vì kỳ III là bạn phải làm các thao tác hoàn toàn thủ công nên chắc chắn phải tìm hiểu kỹ các kỹ thuật đó, còn ở kỳ này để cho công việc đơn giản và dễ nắm bắt hơn tôi sẽ sử dụng thêm một công cụ hỗ trợ việc tải file, kiểm tra phiên bản và chạy file setup tự động. Công cụ tôi sẽ sử dụng là một project mã nguồn mở gọi là NetSparkle. Các bạn có thể tham khảo về NetSparkle tại đây: http://netsparkle.codeplex.com/
A. Chuẩn bị
+ Một Project đơn giản làm mẫu:
Vâng, vẫn là 1 project đơn giản chỉ có 1 form, không có thêm bất cứ thứ gì khác. Nếu bạn thắc mắc tại sao lần trước tôi làm Project mẫu bằng VS2012 còn lần này lại làm bằng VS2010 thì tôi xin trả lời là: VS2012 không còn hỗ trợ trực tiếp việc đóng gói ứng dụng .NET của bạn như các phiên bản trước nữa. Để đóng gói ứng dụng với VS2012, bạn phải cài thêm các công cụ hỗ trợ khác (như InstallShield, Advanced Installer...), và các thành phần đó nằm ngoài khuôn khổ của bài viết này.
+ Một Website là nơi để chứa ứng dụng của bạn trên web. Vâng, update theo kiểu nào thì bạn vẫn cần website để phần mềm có thể tải phiên bản mới về. Tôi vẫn lấy địa chỉ ví dụ là: http://your-website.com. Địa chỉ chứa ứng dụng của bạn sẽ là http://your-website.com/software/AutoUpdateTut2. Bạn vẫn cần có tài khoản FTP để chuyển các file của ứng dụng lên website, tuy nhiên với bài viết này thì Visual Studio không giúp bạn tải file lên tự động, do đó bạn có thể giữ lại tài khoản FTP của bạn để tải file lên bằng các chương trình FTP Client khác.
+ Bộ công cụ NetSparkle được tải về từ CodePlex. Bạn vào liên kết sau: http://netsparkle.codeplex.com/ và thấy nút Download rất to ở bên tay phải. Click vào nó là tải được file về. Sau khi tải về, giải nén ra bạn sẽ có thư mục như sau:
Trong đó có 2 file AppLimit.NetSparkle.dll và AppLimit.NetSparkle.Net40.dll. Nếu bạn sử dụng dotnet 4.0 trở lên thì dùng file thứ 2, nếu thấp hơn 4.0 thì hãy dùng file thứ nhất. Nếu bạn cảm thấy giao diện của NetSparkle quá xấu thì có thể tải Source Code của nó về và chỉnh sửa theo ý bạn. À, còn 1 vấn đề nho nhỏ là ngôn ngữ mặc định trên giao diện của NetSparkle là tiếng Anh. Nếu bạn muốn giao diện tiếng Việt thì cũng cần phải can thiệp vào Source. Bạn nào quan tâm tới vấn đề này thì ta sẽ trao đổi thêm về sau.
B. Thực hiện
1. Reference đến thư viện của NetSparkle
- + Trong Visual Studio, Right Click vào mục Reference và chọn Add Reference
- + Trong cửa sổ Add Reference mới hiện ra, chọn tab Browse
- + Browse đến thư mục NetSparkle bạn đã giải nén được ở bước chuẩn bị, chọn file AppLimit.NetSparkle.Net40.dll và nhấn Ok để Reference file đó vào Project của bạn. Khi kết thúc bạn sẽ được như hình dưới đây
2. Viết Code để kiểm tra phiên bản
+ Kéo từ thanh ToolBox một Button vào Form (khi Click vào Button này ta sẽ bắt đầu kiểm tra phiên bản - Bạn có thể sử dụng các control khác như Menu, ToolStrip... cũng được. Miễn là có sự kiện cho ta viết code)
+ Viết Code cho Form1 như sau:
- using System;
- using System.Windows.Forms;
-
- namespace AutoUpdateTut2
- {
- public partial class Form1 : Form
- {
- AppLimit.NetSparkle.Sparkle _sparkle; //khai báo đối tượng Sparkle để check Update
- public Form1()
- {
- InitializeComponent();
- }
- private void Form1_Load(object sender, EventArgs e)
- {
- //khởi tạo đối tượng Sparkle với địa chỉ web trỏ tới file chứa thông tin về phiên bản trên server
- //file thông tin: version-info.xml là 1 file xml chứa thông tin về phiên bản được đặt trên máy chủ web
- //nội dung file này sẽ được mô tả sau
- _sparkle = new AppLimit.NetSparkle.Sparkle("http://your-website.com/software/AutoUpdateTut2/version-info.xml");
- //bắt Sparkle chạy ngầm và tự động kiểm tra phiên bản mới sau mỗi 1 giờ
- //tham số:
- // doInitialCheck: true=>kiểm tra phiên bản ngay lập tức; false=>1h sau khi gọi hàm này mới tiến hành kiểm tra
- // checkFrequency: chu kỳ kiểm tra phiên bản
- _sparkle.StartLoop(true, new TimeSpan(1, 0, 0));
- }
-
- private void button1_Click(object sender, EventArgs e)
- {
- //ép buộc Sparkle kiểm tra phiên bản ngay lập tức
- _sparkle.StartLoop(true, true);
- }
- }
- }
3. File thông tin phiên bản:
Trong mục 2 ở trên đây, code của bạn có mở liên kết đến file version-info.xml. File này bạn phải tự tạo nó và đặt ở trên máy chủ Web của bạn để phần mềm tải về mỗi lần check update. Nội dung file version-info.xml như sau:
[xml]
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>AutoUpdateTut2</title>
<link>http://your-website.com/software/AutoUpdateTut2/version-info.xml</link>
<description></description>
<language>en</language>
<item>
<title>Version 1.0.1</title>
<sparkle:releaseNotesLink>http://your-website.com/software/AutoUpdateTut2/1.0.1/release-note.xml</sparkle:releaseNotesLink>
<pubDate>Wed, 28 Aug 2013 12:30:00 +7</pubDate>
<enclosure
url="http://your-website.com/software/AutoUpdateTut2/AutoUpdateTut2Setup.msi"
length="5120"
type="application/octet-stream"
sparkle:version="1.0.1"
sparkle:dsaSignature=""/>
</item>
</channel>
</rss>
[/xml]
Nội dung file cũng khá lằng nhằng, nhưng bạn chỉ cần quan tâm 1 số điểm chính sau:
- + Mỗi lần có phiên bản mới, bạn sẽ tạo ra 1 thẻ item giống như thẻ item đã có sẵn trong file
- + Địa chỉ liên kết của sparkle:releaseNotesLink là địa chỉ tới 1 file html đơn thuần. Trong file html đó bạn sẽ viết các mô tả các thay đổi của phiên bản mới. Nội dung file html này sẽ được hiện ra trên form để người dùng xem
- + url: địa chỉ liên kết tới file cài đặt của phiên bản mới. Sparkle sẽ tải file này về máy người dùng và chạy nó lên để tiến hành cập nhật
- + sparkle:version: phiên bản mới. Phiên bản này sẽ được dùng để so sánh với phiên bản đang chạy trên máy khách xem nó mới hay cũ. Vì vậy nếu bạn có phiên bản mới, hãy đặt số phiên bản ở đây cao hơn số phiên bản trên máy khách
Các mục khác, bạn có thể nhập bất kỳ thế nào cũng được
4. Đóng gói ứng dụng
Mọi thứ đã chuẩn bị gần xong rồi, chỉ còn cần có file cài đặt nữa là chạy thôi. Bây giờ ta sẽ tiến hành đóng gói ứng dụng để có file cài đặt. Tôi sẽ đóng gói ứng dụng theo kiểu chia bộ cài đặt thành 2 file khác nhau (1 file EXE và 1 file MSI). Các bạn có lẽ sẽ có thắc mắc tại sao 1 số chương trình Setup thì chỉ cần file EXE, 1 số thì chỉ cần file MSI, 1 số lại cần cả 2. Tôi xin giải thích sơ qua 1 chút:
+ Bản thân các bộ cài đặt theo chuẩn luôn cần có file MSI (Cài đặt bằng file này sẽ giúp phần mềm của bạn được đăng ký với Windows), còn các bộ cài đặt tự làm theo kiểu copy file vào các thư mục cần thiết thì không được tính là chuẩn
+ Nếu bộ cài đặt chỉ có file EXE thì có nghĩa là file MSI đã được nén vào trong file EXE rồi. Khi chạy file exe, nó sẽ giải nén file MSI ra thư mục tạm và tiến hành cài đặt từ thư mục tạm.
+ Một bộ cài đặt chỉ có file MSI: các file cần thiết để chạy chương trình, các thông tin đăng ký phần mềm tất cả đã nằm đủ trong file MSI và đủ để cài đặt chương trình lên máy tính rồi.
+ Một bộ cài đặt có cả file EXE và MSI: Bản thân file MSI đã chứa các thông tin cần thiết để cài đặt chương trình rồi. Bạn chỉ cần chạy file MSI là có thể cài đặt chương trình vào máy tính. Tuy nhiên chương trình được cài đặt chưa chắc đã chạy được trên máy tính đó bởi vì nó còn thiếu các thành phần hỗ trợ (ví dụ: 1 chương trình .NET để chạy được thì cần có .NET Framework). Vậy file EXE ở trong bộ cài đặt (người ta hay gọi nó là BootStrapper) sẽ đóng vai trò kiểm tra các điều kiện cần thiết để chương trình của bạn có thể chạy tốt sau khi cài đặt (ví dụ: kiểm tra xem có .NET Framework chưa? kiểm tra xem có SQL Server chưa? kiểm tra xem có Office chưa...). Nếu các điều kiện kiểm tra đã thỏa mãn, nó sẽ chạy file MSI cho bạn để tiếp tục cài đặt. Nếu không thỏa mãn, hoặc là BootStrapper sẽ báo cho bạn là thiếu công cụ hỗ trợ, hoặc là nó tự động cài các công cụ hỗ trợ cho bạn...
+ Có đôi khi file MSI không được nén và nhúng vào trong file EXE mà cũng không nằm cùng với file EXE. Lúc này file MSI sẽ được đặt ở trên Internet. BootStrapper sau khi kiểm tra các điều kiện đã thỏa mãn thì nó sẽ tải file MSI từ Internet về máy và tiến hành chạy file MSI để cài đặt sau đó. Đây chính là hướng mà tôi sẽ làm cho bộ cài đặt này. Vì chúng ta có 1 website trên Internet nên tôi sẽ đặt file MSI trên website này. BootStrapper sau khi kiểm tra máy tính thỏa mãn các điều kiện thì sẽ tải file MSI về. Cách này khá hay vì bạn sẽ được đảm bảo rằng tất cả các điều kiện cần thiết cho chương trình của bạn chạy được phải thỏa mãn trước khi người dùng có thể cài đặt phần mềm. Nếu bạn cung cấp file EXE và file MSI cùng lúc, nhiều người dùng sẽ chạy file MSI để cài đặt trước và vì thế sẽ gây ra các hiểu lầm không mong muốn. Còn 1 nguyên nhân nữa là khi file MSI được đặt trên Internet, mỗi lần chương trình có cập nhật thì NetSparkle chỉ tải file MSI về để chạy cài đặt mà không cần tải file EXE nữa (vì việc kiểm tra điều kiện đã được thực hiện ở lần cài đặt đầu tiên rồi)
Bây giờ chúng ta sẽ tiến hành tạo bộ cài đặt cho ứng dụng
1. Thêm Project để tạo bộ cài đặt:
+ Trong Visual Studio, chọn menu File > Add > New Project
+ Trong cửa sổ Add New Project, bạn chọn mẫu Project là Setup Project, đặt tên project là AutoUpdateTut2Setup như hình dưới đây
+ Nhấn OK để đồng ý thêm Project, bạn sẽ thấy Solution của mình có dạng như thế này
Kỳ III. Kỹ thuật Update thủ công
Dạo trước do bận công việc nên không có thời gian viết tiếp bài này. Nhân dịp đầu năm mới, chúc anh em sức khỏe dồi dào, gia đình hòa thuận, công việc suôn sẻ, làm ăn phát đạt
Thể theo nguyện vọng của một số anh em muốn tìm hiểu thêm về kỹ thuật update thủ công, mình xin được viết tiếp phần 3 hướng dẫn về việc update thủ công. Do lâu lâu rồi không theo dõi bài viết nên có thể văn phong không được liền mạch với các kỳ trước, mong anh em rộng lượng bỏ qua. Mình cũng xin nhắc lại 1 điểm: bài này được viết theo ý hiểu và quan điểm của mình. Mọi người nếu có thể tham khảo được chút nào thì tham khảo, nếu không thì cũng đừng nên ném đá mình
Về ưu nhược điểm của phương pháp này thì mình đã viết ở các kỳ trước rồi, giờ mình xin đi luôn vào vấn đề:
Về kỹ thuật update, cũng không có nhiều điểm mới so với các phương pháp trước: nghĩa là vẫn tải các file mới từ 1 host về và copy đè vào vị trí các file cũ đã được cài đặt trên máy Local. Với các phương pháp trước, mọi vấn đề về đã được giải quyết tự động cho chúng ta, còn với phương pháp này chúng ta phải tự làm mọi thứ nên sẽ phát sinh một số vướng mắc sau:
1. Khi nào thì ta phải tải file mới về để cập nhật:
Việc phát hiện ra có file mới cần cập nhật là do chúng ta tự quyết định. Chúng ta có thể thực hiện việc kiểm tra có file mới cần cập nhật hay không một lần vào lúc khởi động chương trình, hoặc lúc tắt chương trình, hoặc là định kỳ kiểm tra bao nhiêu phút một lần. Tùy thuộc vào mức độ quan trọng của việc cập nhật, hoặc tùy thuộc vào kỹ năng của mọi người mà mình sẽ chọn ra thời điểm cập nhật hợp lý nhất. Ở các phần tiếp theo của bài này, để đơn giản mình sẽ chọn cách kiểm tra cập nhật 1 lần vào lúc khởi động chương trình.
2. File nào được coi là file mới cần cập nhật:
Có nhiều tiêu chí để đánh giá 1 file là mới và cần cập nhật, nhưng mình chọn ra 2 tiêu chí cơ bản nhất là dung lượng file (file size) và thời gian sửa đổi cuối cùng (last modified date). Nếu một file ở máy Local có ít nhất 1 trong 2 tiêu chí trên khác với file trên Host thì file đó cần thiết phải cập nhật
3. So sánh file ở máy Local với file trên Host như thế nào:
Để so sánh file ở Local với file trên Host, bạn không cần thiết phải tải tất cả các file ở trên Host về máy rồi mới tiến hành so sánh vì như vậy với các chương trình lớn có nhiều file, dung lượng file lớn thì việc tải tất cả các file về sẽ là 1 sự lãng phí. Bạn chỉ cần đặt một tệp tin (ví dụ: 1 tệp tin dạng text đơn thuần) trên Host, trong đó có chứa thông tin về các file đang nằm trên host. Ứng dụng khi kiểm tra cập nhật sẽ tải tệp tin này về và phân tích tệp tin để tìm ra tệp cần phải cập nhật. Tôi sẽ sử dụng một tệp tin dạng text đơn giản gồm các trườngthông tin như sau (phân cách các trường bởi một ký tự Tab \t)
<Tên file>\t<thời gian sửa đổi cuối>\t<dung lượng>
ví dụ về 1 file update.txt
-
Program1.exe 20150224143200 152021
-
data.txt 20150224143200 3205
4. Ghi đè file đang sử dụng
Giả sử ứng dụng của bạn là Program1.exe cần phải cập nhật 2 file như nội dung file text ở mục 3 (là: program1.exe và data.dat). Một vấn đề đặt ra là: sau khi bạn tải tệp tin Program1.exe từ Host về Local rồi, làm thế nào để bạn copy tệp tin Program1.exe mới đè vào tệp tin cũ vì chương trình của bạn đang chạy. Khi file Program1.exe (là chương trình của bạn) đang chạy thì không thể copy file mới đè vào vị trí của nó - đó là cơ chế của windows. Để giải quyết bài toán này, chúng ta phải sử dụng một tệp tin exe phụ (ta đặt tên là updater.exe). Quy trình làm việc khi thực hiện Update như sau: Program1.exe tải tệp tin update.txt về, phân tích để kiểm tra xem có file nào mới không? Nếu có file mới thì tải file mới đó về một thư mục tạm. Sau khi tải xong sẽ gọi file updater.exe và tự thoát chương trình. Khi đó, Program1.exe đã thoát nên Updater.exe có thể copy file Program1.exe mới từ thư mục tạm đè vào vị trí của file cũ. Sau khi copy đè tất cả các file xong, Updater.exe sẽ gọi Program1.exe để chạy lại chương trình chính, còn bản thân nó thì tự thoát. Như vậy là ta đã có chương trình với file Program1.exe mới trên máy Local.
Nếu bạn viết tốt file updater.exe thì có thể viết 1 lần rồi sử dụng mãi mãi được, thậm chí là sử dụng cho cả project khác mà không cần chỉnh sửa gì. Tuy nhiên nếu bạn viết chưa được tốt thì cũng không sao, bạn hoàn toàn có thể update cho file Updater.exe bất cứ lúc nào. Program1.exe sẽ làm nhiệm vụ tải các file mới về. Nếu bạn có 1 file updater.exe mới thì bạn chỉ cần sử dụng Program1.exe để thực hiện lệnh copy.
Như vậy, quy trình chung sẽ là: Program1.exe thực hiện kiểm tra và cập nhật file mới cho updater.exe. Còn updater.exe sẽ thực hiện cập nhật cho Program1.exe
5. Quyền ghi file lên máy Local
Trên các máy tính chạy windows 7, 8 bạn sẽ không thể copy file vào Program Files nếu không có quyền Admin. Vì vậy chương trình của chúng ta phải yêu cầu quyền Admin khi cần ghi đè file. Chúng ta sẽ nói thêm về phần này ở phía dưới.
Trên đây là 1 số lý thuyết, còn bây giờ chúng ta sẽ đi vào ví dụ cụ thể để dễ hình dung. Để làm ví dụ này, chúng ta cần chuẩn bị 1 số công cụ như sau:
1. Visual Studio: hiện tại mình đang dùng bản VS2013 nhưng các bạn có thể dùng các bản thấp hơn (2005, 2008, 2010...) hoặc là bản Visual Studio Express cũng không sao. Ví dụ này của chúng ta không yêu cầu cao. Mình sẽ tạo Project trên .NET framework 2.0
2. Một Host để chứa các file cần cập nhật. Host này cũng không yêu cầu nhiều, chúng ta chỉ chứa các file trên đó để chương trình ở Local tải về nên có thể dùng host ASP, PHP tùy ý bạn. Chúng ta sẽ tải file theo kiểu HTTP bình thường nên nếu bạn nhập địa chỉ của file lên thanh địa chỉ của trình duyệt mà có thể tải được file về là đạt. Mình sẽ làm ví dụ luôn với IIS, chạy trên máy Local. Giả sử mình tạo một website trong IIS, ở cổng 8088 như hình sau:
Tạo một website tại cổng 8088 trong IIS
Sau khi chuẩn bị sẵn sàng 2 thứ trên, chúng ta sẽ bắt tay vào làm Project, các bước lần lượt như sau
1. Tạo Project
Chúng ta sẽ tạo một Project dạng Exe đơn giản trong Visual Studio với .NET framework 2.0 bằng cách: từ menu File, chọn mục New > Project, sau đó nhập thông tin cho Project như hình dưới
Tạo Project trong Visual Studio
Như trên đã phân tích, chúng ta có 2 file thực thi là Program1.exe và Updater.exe. Vì vậy chúng ta thêm tiếp 1 Project nữa cho ví dụ của chúng ta. Từ màn hình của Visual Studio (đã tạo 1 project ở bước trước), chúng ta vào menu File, chọn Add > New Project. Sau đó đặt tên Project mới là "Updater", vẫn là project kiểu WinForm, .NET framework 2.0 như trên.
Kết thúc việc tạo Project, chúng ta sẽ có 1 Solution với 2 Project kiểu WinForm như sau:
2. Kiểm tra các tệp tin cần cập nhật
Việc kiểm tra các tệp tin cần cập nhật sẽ được thực hiện khi Program1.exe chạy, do vậy chúng ta sẽ viết code cho sự kiện Load Form1 của Project "Program1"
-
private void Form1_Load(object sender, EventArgs e)
-
{
-
CheckForUpdate();
-
}
-
private void CheckForUpdate()
-
{
-
}
-
Để kiểm tra xem có tệp tin nào cần cập nhật hay không, chương trình của chúng ta cần tải tệp tin Update.txt từ host về, sau đó phân tích. Tôi viết 1 hàm chung để tải file từ host về máy Local như sau. (Lưu ý các bạn, ở đây tôi sẽ bỏ qua phần lớn việc bắt lỗi để cho phần code hướng dẫn ngắn gọn và dễ hiểu)
-
private void DownloadFile(string remotePath, string localPath)
-
{
-
WebClient client = new WebClient();
-
//tải tệp tin tại địa chỉ remotePath và lưu về máy local tại địa chỉ localPath
-
client.DownloadFile(remotePath, localPath);
-
}
-
Sau khi tải tập tin update.txt về thư mục tạm, chúng ta sẽ tiến hành đọc tập tin đó để phân tích. Tập tin của chúng ta là 1 tập tin văn bản đơn thuần, gồm nhiều dòng. Mỗi dòng sẽ chứa thông tin về 1 file. Trong 1 dòng thì có 3 phần: tên file, ngày tháng thay đổi và kích thước file được phân cách nhau bởi dấu Tab. Chúng ta có thể dễ dàng dùng phương pháp Split chuỗi để lấy được các thông tin cần thiết:
-
//đọc toàn bộ nội dung file vào biến
-
string fileContent = System.IO.File.ReadAllText(filePath);
-
//split nội dung file theo từng dòng (bằng ký tự CrLf)
-
string[] lines = fileContent.Split(new [] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
-
//duyệt từng dòng (tương ứng với từng file)
-
foreach (string line in lines)
-
{
-
//với mỗi dòng, phân tách các phần bởi dấu tab
-
string[] parts = line.Split(new[] {'\t'}, StringSplitOptions.RemoveEmptyEntries);
-
//tên file, nằm ở ngay phần đầu tiên
-
string fileName = parts[0];
-
//ngày tháng thay đổi của file, nằm ở phần 2
-
long modifiedDate = Convert.ToInt64(parts[1]);
-
//kích thước file nằm ở phần cuối cùng
-
long fileSize = Convert.ToInt64(parts[2]);
-
}
-
Sau khi lấy được thông tin file ở host (bằng việc phân tích tệp tin update.txt), ta sẽ so sánh các thông tin này với tệp tin ở máy Local để quyết định xem tệp tin đó có cần được update hay không. Để đọc thông tin về tệp tin ở máy Local, ta sử dụng đối tượng FileInfo:
-
//lấy thông tin của file
-
System.IO.FileInfo fileInfo = new FileInfo(localPath);
-
//kiểm tra xem kích thước và ngày tháng Modified giữa tệp Local với tệp remote có khác nhau không?
-
//Nếu có 1 thông số khác nhau thì coi như file đã thay đổi và cần phải cập nhật
-
if ((fileInfo.Length != fileSize) || (fileInfo.LastWriteTime.Ticks != modifiedDate))
-
{
-
//thêm file đã thay đổi vào danh sách để tải về sau này
-
FileList.Add(fileName);
-
}
-
Sau khi xác định được các file đã có thay đổi và cần tải về, ta sẽ tiến hành tải các file đó về thư mục tạm.
-
//duyệt danh sách các file và tải về thư mục tạm
-
foreach (string fileName in fileList)
-
{
-
//tạo đường dẫn tạm để lưu file
-
string localPath = System.IO.Path.GetTempPath() + TEMP_DIR + "\" + fileName;
-
//xác định đường dẫn file trên host
-
string remotePath = HOST_ADDRESS + "/" + fileName;
-
//tải file từ host về thư mục tạm
-
DownloadFile(remotePath, localPath);
-
}
-
//gọi chương trình Update.exe để thực hiện việc ghi đè file mới lên file cũ
-
Process.Start("Updater.exe");
-
//sau đó thoát khỏi chương trình chính để giải phóng các tệp tin đang sử dụng
-
Application.Exit();
-
Sau khi tải xong các tệp tin cần update về thư mục tạm thì cơ bản công việc của chương trình chính đã kết thúc. Ta cần phải thoát khỏi chương trình chính để giải phóng việc sử dụng các tệp tin. Trước khi thoát, ta sẽ gọi tệp tin Updater.exe để nó thực hiện nốt công việc còn lại là ghi đè các file mới tải về vào vị trí các file cũ.
3. Ghi đè các file cần cập nhật
Phần công việc ghi đè các file sẽ do file Updater.exe (tạo bở project Updater) thực hiện, do vậy sau đây ta sẽ code cho sự kiện Form_Load của Form1 trong project Updater.
-
private void Form1_Load(object sender, EventArgs e)
-
{
-
//đợi 2 giây, cho chương trình chính (Program1.exe) thoát hoàn toàn
-
//các bạn có thể sử dụng các kỹ thuật cao hơn như kiểm tra Process để xác định xem
-
//khi nào Program1.exe đã thoát hoàn toàn thì mới tiến hành ghi đè file. Nếu không sẽ phát sinh lỗi
-
System.Threading.Thread.Sleep(2000);
-
//tiến hành ghi đè file
-
}
-
-
private void CopyFiles()
-
{
-
}
-
Trong hàm CopyFiles, đơn giản là ta đọc tất cả các file trong thư mục tạm (nơi Program1.exe đã tải về) và ghi đè lên file cũ
-
//xác định thư mục hiện thời, nơi chương trình đang chạy
-
string currentDirectory = Environment.CurrentDirectory;
-
//xác định thư mục tạm, nơi Program1.exe đã tải các file cần cập nhật về
-
string tempDirectory = System.IO.Path.GetTempPath() + TEMP_DIR;
-
//lấy danh sách tất cả các file trong thư mục tạm
-
string[] fileList = System.IO.Directory.GetFiles(tempDirectory);
-
//duyệt từng file và copy đè lên file cũ trong thư mục đang chạy chương trình
-
foreach (string sourceFile in fileList)
-
{
-
//tách tên file ra khỏi đường dẫn (tên file sẽ dùng để tạo đường dẫn đích cần copy đè)
-
string fileName = System.IO.Path.GetFileName(sourceFile);
-
//tạo đường dẫn đích để copy file mới tới
-
string destinationFile = currentDirectory + "\" + fileName;
-
//thực hiện copy đè
-
System.IO.File.Copy(sourceFile, destinationFile, true);
-
}
-
//sau khi copy đè tất cả các file xong, ta sẽ tiến hành gọi lại chương trình chính (Program1.exe) để chạy lại chương trình
-
Process.Start("Program1.exe");
-
//và thoát khỏi chương trình update
-
Application.Exit();
-
sau khi copy đè các file cần thiết xong, ta sẽ gọi lại chương trình chính để chạy lại nó, rồi thoát khỏi chương trình Updater. Như vậy là đã hoàn tất quá trình Update
Trên đây là 1 quy trình đơn giản nhất cho việc Update chương trình bằng cách thủ công. Do code của chương trình ví dụ đa phần là các đoạn code thực hiện thao tác đơn giản (đọc file text, split chuỗi, copy file...) và cũng khá dài nên mình không tiện ghi tất cả ra. Mình đính kèm Source Code ở dưới bài viết này, các bạn có thể tải về để tham khảo. Trong Source Code mình đã chú thích chi tiết cho từng dòng nên cũng sẽ không khó khăn gì khi đọc cả
4. Test chương trình
Để test chương trình, các bạn có thể:
+ tải project ví dụ ở dưới bài viết này về, mở trong Visual Studio và build
+ Mở thư mục "Updater\Bin\Debug", copy tệp tin Updater.exe vào thư mục "Program1\Bin\Debug" - Việc copy này là cần thiết vì Program1.exe khi chạy có gọi tập tin Updater.exe bằng lệnh Process.Start. Do đó 2 file exe phải nằm cạnh nhau
copy tệp updater.exe vào thư mục Bin\Debug của Program1
+ Tạo file update.txt trên host với nội dung như đã mô tả ở phần đầu của bài viết
+ Copy file Program1.exe từ thư mục "Program1\Bin\Debug" lên host
+ Tạo 1 file data.txt tùy ý trên host (để giả lập trường hợp ta cần update 2 file), khi đó, cấu trúc thư mục trên host sẽ như hình sau
các file test đặt trên host
+ Quay lại Visual Studio và Run hoặc Debug project
5. Bàn luận thêm
+ Tệp tin update.txt ở trên chỉ là 1 ví dụ, mình nhập các con số ngẫu nhiên vào vị trí Modified Date và File Size. Nếu làm chương trình thật, các bạn cần điền vào đó thông tin thật của tệp tin cần update. Tất nhiên là nên tạo 1 tool nhỏ để đọc thông tin file ra và lấy Size, Modified Date rồi ghi vào file theo cấu trúc mong muốn
+ Quá trình tải các tệp tin từ host thực sự ở trên mạng về có thể gặp nhiều trở ngại do lỗi mạng, tệp tin quá lớn nên thời gian tải lâu... nên các bạn cần thực hiện việc update trong Thread hoặc Background Worker và sử dụng các loại thanh Progress, Indicator... để thể hiện quá trình cập nhật đang diễn ra tới đâu
+ Với các tệp tin chứa dữ liệu việc Update bằng cách ghi đè file có thể làm mất dữ liệu khách hàng đã lưu trên máy, vì vậy hãy cân nhắc kỹ trước khi quyết định có update các tệp này hay không
+ Nếu cần update dữ liệu trong CSDL, bạn có thể tạo các tệp tin script (*.sql). Chương trình Updater có thể copy các tệp script này vào 1 vị trí quy ước nào đó để ở lần khởi động sau của chương trình Program1.exe, chương trình chính sẽ đọc các tệp script này và thực thi các câu SQL để update CSDL
Program1.zip
|