• Thứ Sáu, 19/10/2007 09:44 (GMT+7)

    Lập trình VC++ cập nhật giờ hệ thống

    Câu hỏi :

    Xin hướng dẫn lập trình VC++ cập nhật giờ hệ thống, tôi có viết đoạn code VC++ sau nhưng nó không có tác dụng:

     SYSTEMTIME sys;
     GetSystemTime(&sys);
     sys.wHour=m_txtH; //m_txtH là biến chuỗi gãn với textbox giờ
     sys.wMinute=m_txtM; //m_txtM là biến chuỗi gãn với textbox phút
     sys.wSecond=m_txtS; //m_txtS là biến chuỗi gãn với textbox giây
     SetSystemTime(&sys);



    Trả lời :

     Bạn đã gọi đúng hàm API SetSystemTime() để hiệu chỉnh lại ngày/giờ cho hệ thống. Đoạn code của bạn cơ bản là đúng, tuy nhiên bạn hãy chú ý 3 vấn đề sau đây:

     1. Các thuộc tính wHour, wMinute, wSecond có kiểu nguyên (số) nên bạn cần gán giá trị số cho chúng. Bạn nên khai báo các biến m_txtH, m_txtM, m_txtS có kiểu nguyên (int) chứ không phải kiểu chuỗi (CString). Trong trường hợp các biến m_txtH, m_txtM, m_txtS có kiểu chuỗi, bạn cần gọi hàm thích hợp (atoi()...) để đổi chúng thành số nguyên trước khi gán vào thuộc tính tương ứng của record SYSTEMTIME.

     2. Giá trị ngày/giờ được dùng trong 2 hàm Get và SetSystemTime() là ngày giờ UTC, nếu ứng dụng cho phép người dùng nhập giờ/phút/giây theo định dạng địa phương (thí dụ giờ Việt Nam), bạn cần gọi hàm API Windows (TzSpecificLocalTimeToSystemTime) để đổi nó sang chuẩn UTC trước khi dùng trong hàm SetSystemTime(). Bạn cũng có thể dùng trực tiếp 2 hàm Get và SetLocalTime().

     3. Nếu đoạn code của bạn chạy trên Windows ME trở về trước thì nó sẽ luôn cập nhật được ngày/giờ hệ thống, tuy nhiên nếu chạy trên Windows NT/2000 hay XP thì chưa chắc. Lưu ý rằng các hệ thống Windows NT/2000 hay XP có tính an toàn thông tin rất cao, mỗi người làm việc đều phải có tài khoản (account), mỗi account qui định người dùng có những quyền gì trên hệ thống. Như vậy khi ứng dụng của bạn chạy với account nào thì nó có quyền theo account đó, nếu account đó không có quyền thay đổi ngày/giờ hệ thống thì đoạn code trên sẽ không thể cập nhật ngày/giờ hệ thống được. Ngoài account quản trị (admin) ra, các account khác thường có quyền truy xuất rất hạn chế vào hệ thống, và thường không có quyền thay đổi ngày/giờ hệ thống. Để viết ứng dụng luôn cập nhật được ngày/giờ hệ thống, bất chấp ứng dụng được chạy bởi người dùng nào, bạn cần thêm đoạn code “xin phép” quyền thay đổi ngày/giờ trước khi thực hiện thay đổi. Sau đây là hàm UpdatePrivilege(), hàm này sẽ thiết lập/xóa quyền truy xuất vào 1 tài nguyên nào đó của hệ thống:

     // thiết lập hay cấm quyền truy xuất
     BOOL UpdatePrivilege(LPCTSTR lpszPrivilege, BOOL bEnable) {
     TOKEN_PRIVILEGES tp;
     LUID luid;
     HANDLE hToken;
     //lấy handle của process ứng dụng
     if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
     return FALSE;
     //lấy luid của quyền cần thiết lập/xóa
     if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid)) {
     printf("LookupPrivilegeValue error: %u\n", GetLastError() );
     return FALSE;
     }
     //xác định hoạt động thiết lập/cấm quyền
     tp.PrivilegeCount = 1;
     tp.Privileges[0].Luid = luid;
     if (bEnable)
     tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
     else
     tp.Privileges[0].Attributes = 0;
     
     // gọi AdjustTokenPrivileges để thiết lập/cấm quyền.
     if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
     printf("AdjustTokenPrivileges error: %u\n", GetLastError());
     return FALSE;
     }
     // kiểm tra kết quả.
     if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
     printf("The token does not have the specified privilege. \n");
     return FALSE;
     }
     return TRUE;
     }
     
     Còn dưới đây là hàm hiệu chỉnh giờ/phút/giây của hệ thống mà chúng tôi viết lại cho bạn:
     //hàm xử lý button Update
     void CYourFormDlg::OnUpdate() {
     // TODO: Add your control notification handler code here
     //thiết lập quyền hiệu chỉnh ngày/giờ
     if (UpdatePrivilege(SE_SYSTEMTIME_NAME, 1)) {
     SYSTEMTIME sys;
     //lấy ngày/giờ hiện hành của hệ thống
     GetSystemTime(&sys);
     //hiệu chỉnh 1 số field cần thiết
     sys.wHour=m_intH; //m_intH là biến int gãn với textbox giờ
     sys.wMinute=m_intM; //m_intM là biến int gãn với textbox phút
     sys.wSecond=m_intS; //m_intS là biến int gãn với textbox giây
     //hiệu chỉnh lại ngày/giờ hệ thống
     SetSystemTime(&sys);
     //cấm quyền hiệu chỉnh ngày/giờ
     UpdatePrivilege(SE_SYSTEMTIME_NAME, 0);
     }
     }
     

    Chuyên mục: Lập trình