Trong hai phần đầu của loạt bài này chúng ta đã biết cách thay đổi địa chỉ IP của một bộ điều hợp mạng trên máy tính Windows dùng VBScript. Chúng ta cũng đã biết về nhiều khái niệm cơ bản của Windows scripting như lớp (class), đối tượng (object), thuộc tính (property), phương thức (method) và các kiểu biến khác nhau như biến xâu (string), biến mảng (array), biến nguyên (integer), biến tập hợp (collection). Kết thúc ở phần một là một script đơn giản thực hiện được nhiệm vụ thay đổi địa chỉ, và phần hai bổ sung thêm nhiều tính năng hỗ trợ quan trọng khác như định nghĩa các biến, triển khai kiểm soát lỗi, nhận thông tin người dùng đầu vào, hiển thị xác nhận dữ liệu đầu ra và dẫn giải script bằng các chú thích.
Script cuối cùng của chúng ta hoạt động tốt như mong đợi, nhưng vẫn còn nhiều thứ rất khó hiểu. Ví dụ như dòng lệnh sau:
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Trong phần đầu chúng ta có chú thích: “Dòng lệnh này kết nối tới namespace root\cimv2 trên máy cục bộ bằng cách định nghĩa một đối tượng có tên objWMIService và đặt nó bằng với điều khiển trả về từ phương thức GetObject”.
Điều này có nghĩa là gì? WMI là gì và nó hoạt động như thế nào? Vì sao khái niệm này lại quan trọng khi muốn viết được một script tốt để quản trị các máy Windows?
Hiểu về WMI
WMI ra đời từ thời kỳ của Windows 98 hoặc sớm hơn. Trước đây nó được gọi với cái tên khác Web-Based Enterprise Management (WBEM), tức Công cụ quản lý doanh nghiệp dựa trên nền tảng Web. WBEM là công nghệ hợp tác phát triển bởi Microsoft, Cisco, Intel, Compaq và BMC Software nhằm hỗ trợ quản lý các hệ thống máy chủ và máy để bàn trong môi trường doanh nghiệp. WMI cung cấp mô hình thể hiện, lưu trữ và truy vấn cấu hình, thông tin trạng thái hay nhiều khía cạnh hoạt động khác của các máy Windows. Các nhà phát triển có thể dùng WMI để viết script hoặc quản lý mã nguồn để xem hay chỉnh sửa các thiết lập cấu hình trên máy Windows, xem trạng thái của các ứng dụng, dịch vụ Windows và thực hiện toàn bộ nhiều công việc hữu ích khác của một quản trị viên như triển khai, bảo trì, gỡ lỗi các mạng Windows.
Nói cách khác, nói tới WMI tức là nói tới:
- Hệ điều hành Windows: làm việc trên môi trường Windows và cho các máy chạy Microsoft Windows.
- Management: có thể được dùng để quản lý các máy tính này.
- Instrumentation: cung cấp nhiều công cụ để xem và chỉnh sửa những thứ chạy bên trong các máy tính này.
Bạn có thể ví máy tính Windows giống như một chiếc xe ô tô và WMI giống như nguồn điện hay các thiết bị điện cho phép bảng đo đồng hồ hiển thị tốc độ, nhiệt độ động cơ, RPM… của ô tô. Bản thân các điều khiển bảng đo đồng hồ này không phải là WMI. Bạn cần phải đưa ra cách lấy thông tin từ bảng điện và thể hiện nó ở dạng có thể đọc được. Viết VBScript sử dụng WMI cũng giống như tạo các bảng đo đồng hồ trung gian, liên hệ với thiết bị bên dưới ô tô và hiển thị thông tin đối tượng để có thể cho bạn biết cần phải làm gì và điều khiển nào động cơ đang thực hiện. Nói cách khác, Windows tích hợp tất cả công cụ dựng sẵn này qua WMI. Bạn chỉ cần biết cách làm sao lấy chúng ra để thực hiện những điều mình muốn như thay đổi địa chỉ IP, xem múi giờ, khởi động lại máy từ xa, hiển thị danh sách các bản vá đã được cài đặt…
WMI Namespace
Đến giờ, chúng ta vẫn chưa biết gì về cách thức hoạt động của WMI? Cũng không hẳn thế. Thực ra, để hiểu được về WMI đòi hỏi chúng ta cần phải kiên nhẫn và có một chút kiến thức cơ sở. Hãy bắt đầu bằng cách xem xét các namespace WMI. Trong thuật ngữ WMI, namespace là một cơ sở dữ liệu logic của các lớp và các thể hiện của chúng. Dưới đây là một script đơn giản có tên ShowNamespaces.vbs, liệt kê tất cả các namespace WMI bên dưới namespace gốc:
Set objWMIService = GetObject("winmgmts:\\.\root")
Set colNamespaces = objWMIService.InstancesOf("__NAMESPACE")
For Each objNamespace In colNamespaces
WScript.Echo objNamespace.Name
Next
Và kết quả chạy script trên một máy Windows XP là:
C:\scripts>cscript ShowNamespaces.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
SECURITY
RSOP
Cli
SecurityCenter
WMI
CIMV2
Policy
Microsoft
DEFAULT
directory
subscription
Mỗi namespace này có thể là một nguồn cho phép bạn truy vấn thông tin liên quan đến trạng thái hay cấu hình một số yếu tố của máy tính Windows (thông thường cũng có thể chỉnh sửa cấu hình đó). Các namespace này được tổ chức theo kiểu cấu trúc phân tầng như cấu trúc thư mục trên ổ cứng. Ví dụ, chúng ta có thể hiển thị tất cả namespace dưới namespace gốc root\CIMV2 bằng cách thay đổi dòng đầu tiên trong script như sau:
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Khi chạy script đã được thay đổi, kết quả có dạng:
C:\scripts>cscript ShowNamespaces.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
ms_409
Applications
Thực tế, root\CIMV2 là namespace WMI mặc định trên các máy Windows. Điều này có nghĩa là nếu bạn không mô tả một namespace để kết nối tới trong dòng đầu tiên của script, WMI sẽ mặc định tự động kết nối tới namespace root\CIMV2. Vì thế, nếu chúng ta thay đổi dòng đầu tiên thành:
Set objWMIService = GetObject("winmgmts:\\")
thì kết quả cũng giống như trên. Chú ý là chúng ta có thể bỏ phần trước trong winmgmts:\\.\root\CIMV2 đi. Nhớ lại trong bài một, phần trước thể hiện máy cục bộ và mặc định WMI cho rằng bạn muốn làm việc với máy cục bộ. Nhưng thực tế, khi viết script người ta thường sử dụng các biến (và định nghĩa chúng). Vì thế ở đây chúng ta có thể dùng một script phổ biến hơn để hiển thị các namespace:
Option Explicit
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim objWMIService
Dim colNamespaces
Dim objNamespace
strComputer = "."
strWMINamespace = "\root\CIMV2"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace)
Set colNamespaces = objWMIService.InstancesOf("__NAMESPACE")
For Each objNamespace In colNamespaces
WScript.Echo objNamespace.Name
Next
Tại sao chúng ta cần tìm hiểu tất cả các vấn đề này? Lý do chính là bởi tính linh hoạt! Ví dụ, nếu cần chạy script trên một máy từ xa, chúng ta có thể thay đổi biến strComputer thành địa chỉ của máy từ xa. Hoặc nếu cần hiển thị một phần khác của namespace, chúng ta có thể thêm một vài dòng vào script để nó nhận dữ liệu đầu vào của người dùng trên biến strWMINamespace.
Nhà cung cấp WMI
Tìm ra đúng namespace là thách thức đầu tiên (mặc dù hầu hết các trường hợp kết nối tới namespace mặc định là đủ). Ngoài ra bạn còn cần tìm ra đúng nhà cung cấp phù hợp để truy vấn hoặc update dữ liệu trên hệ thống bạn đang hướng đến. Dưới đây là script có tên ShowProviders.vbs, hiển thị tất cả nhà cung cấp WMI cho namespace root\CIMV2:
Option Explicit
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim objWMIService
Dim colWin32Providers
Dim objWin32Provider
strComputer = "."
strWMINamespace = "\root\CIMV2"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace)
Set colWin32Providers = objWMIService.InstancesOf("__Win32Provider")
For Each objWin32Provider In colWin32Providers
WScript.Echo objWin32Provider.Name
Next
Và kết quả sau khi chạy script này trên một máy Windows XP là:
C:\scripts>cscript ShowProviders.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Win32_WIN32_TSLOGONSETTING_Prov
MS_NT_EVENTLOG_PROVIDER
Win32_WIN32_TSENVIRONMENTSETTING_Prov
SCM Event Provider
ProviderSubSystem
VolumeChangeEvents
NamedJobObjectLimitSettingProv
HiPerfCooker_v1
WMIPingProvider
Microsoft WMI Forwarding Event Provider
Win32_WIN32_TSNETWORKADAPTERSETTING_Prov
SystemConfigurationChangeEvents
Win32_WIN32_TERMINALSERVICE_Prov
Win32_WIN32_TSREMOTECONTROLSETTING_Prov
Win32_WIN32_TSNETWORKADAPTERLISTSETTING_Prov
Win32_WIN32_COMPUTERSYSTEMWINDOWSPRODUCTACTIVATIONSETTING_Prov
Win32_WIN32_TSSESSIONDIRECTORY_Prov
CmdTriggerConsumer
Standard Non-COM Event Provider
SessionProvider
WBEMCORE
RouteEventProvider
WhqlProvider
Win32_WIN32_TSSESSIONSETTING_Prov
Win32_WIN32_TERMINALTERMINALSETTING_Prov
Win32_WIN32_TSCLIENTSETTING_Prov
Win32_WIN32_TERMINALSERVICESETTING_Prov
WMI Kernel Trace Event Provider
Win32_WIN32_PROXY_Prov
NamedJobObjectProv
MS_Shutdown_Event_Provider
SECRCW32
Win32ClockProvider
MS_Power_Management_Event_Provider
Win32_WIN32_WINDOWSPRODUCTACTIVATION_Prov
RouteProvider
Cimwin32A
Msft_ProviderSubSystem
Win32_WIN32_TERMINALSERVICETOSETTING_Prov
NamedJobObjectSecLimitSettingProv
Win32_WIN32_TSSESSIONDIRECTORYSETTING_Prov
Win32_WIN32_TSPERMISSIONSSETTING_Prov
Win32_WIN32_TSACCOUNT_Prov
Win32_WIN32_TERMINAL_Prov
MSIProv
DskQuotaProvider
NetDiagProv
Win32_WIN32_TSGENERALSETTING_Prov
CIMWin32
NamedJobObjectActgInfoProv
NT5_GenericPerfProvider_V1
WMI Self-Instrumentation Event Provider
MS_NT_EVENTLOG_EVENT_PROVIDER
Nghe chừng có vẻ quá nhiều! Nhưng dùng danh sách các nhà cung cấp này, bạn có thể dễ dàng tìm kiếm trên MSDN để biết thêm thông tin về một nhà cung cấp cụ thể và tìm kiếm phương thức hỗ trợ.
Các lớp WMI
Bên cạnh namespace và provider (nhà cung cấp), bạn cũng cần phải hiểu về các lớp WMI nếu muốn tăng cường thêm sức mạnh của WMI cho các hoạt động quản trị Windows trên script. Lớp là một mẫu của kiểu đối tượng bạn có thể quản lý bằng WMI. Ví dụ lớp có tên Win32_LogicalDisk là một mẫu đĩa logic trên các máy Windows, và WMI dùng lớp này để tạo một thể hiện của Win32_LogicalDisk cho từng đĩa được cài.
Dưới đây là một script có tên ShowClasses.vbs hiển thị tất cả các lớp (có khả năng là các đối tượng có thể quản lý) của namespace root\CIMV2:
Option Explicit
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim objWMIService
Dim colClasses
Dim objClass
strComputer = "."
strWMINamespace = "\root\CIMV2"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace)
Set colClasses = objWMIService.SubclassesOf()
For Each objClass In colClasses
WScript.Echo objClass.Path_.Path
Next
Và một số kết quả sau khi chạy script này trên máy Windows XP:
C:\scripts>cscript ShowClasses.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
\\XP\ROOT\CIMV2:__SystemClass
\\XP\ROOT\CIMV2:__thisNAMESPACE
\\XP\ROOT\CIMV2:__Provider
\\XP\ROOT\CIMV2:__Win32Provider
\\XP\ROOT\CIMV2:__IndicationRelated
\\XP\ROOT\CIMV2:__EventGenerator
\\XP\ROOT\CIMV2:__TimerInstruction
\\XP\ROOT\CIMV2:__IntervalTimerInstruction
...
\\XP\ROOT\CIMV2:MSFT_WMI_GenericNonCOMEvent
\\XP\ROOT\CIMV2:MSFT_WmiSelfEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_OperationEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_ComServerLoadOperationEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_InitializationOperationFailureEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_LoadOperationEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_OperationEvent_Pre
\\XP\ROOT\CIMV2:Msft_WmiProvider_DeleteClassAsyncEvent_Pre
\\XP\ROOT\CIMV2:Msft_WmiProvider_GetObjectAsyncEvent_Pre
...
\\XP\ROOT\CIMV2:Win32_ComputerSystemEvent
\\XP\ROOT\CIMV2:Win32_ComputerShutdownEvent
\\XP\ROOT\CIMV2:Win32_SystemTrace
\\XP\ROOT\CIMV2:Win32_ModuleTrace
\\XP\ROOT\CIMV2:Win32_ModuleLoadTrace
\\XP\ROOT\CIMV2:Win32_ThreadTrace
\\XP\ROOT\CIMV2:Win32_ThreadStartTrace
\\XP\ROOT\CIMV2:Win32_ThreadStopTrace
\\XP\ROOT\CIMV2:Win32_ProcessTrace
\\XP\ROOT\CIMV2:Win32_ProcessStartTrace
\\XP\ROOT\CIMV2:Win32_ProcessStopTrace
...
Lại một lần nữa bạn thấy có vẻ quá nhiều và rắc rối, nhưng dùng danh sách này bạn có thể tìm trên MSDN thông tin liên quan đến một lớp WMI cụ thể dễ dàng hơn. Từ đó có thể tìm ra các thuộc tính và phương thức đi kèm với nó.
Sử dụng WMI
Chúng ta hãy sử dụng thực tiễn những thứ đã được nói lý thuyết ở trên. Một trong các lớp script ở trên hiển thị là Win32_TimeZone và chúng ta sẽ dùng nó để hiển thị múi giờ đã cấu hình trên máy tính. Đầu tiên chúng ta cần tìm thêm thông tin về lớp này trên MSDN (gõ từ khoá tìm kiếm "Win32_TimeZone class”). Từ trang kết quả, chúng ta có thể tìm các thuộc tính và phương thức lớp này hỗ trợ (mặc dù thực tế thì lớp cụ thể này chỉ có thuộc tính, không có phương thức) và dùng các thông tin tìm thấy để viết script mình muốn.
Một thử nghiệm cho cho thấy, thuộc tính chúng ta cần tìm là Caption, vì đây là dạng dễ đọc nhất về thông tin múi giờ lưu trữ trên máy. Dưới đây là script có tên DisplayTimeZone.vbs mà chúng ta sẽ dùng để truy vấn thông tin từ WMI và hiển thị nó:
Option Explicit
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim strWMIQuery
Dim objWMIService
Dim colItems
Dim objItem
strComputer = "."
strWMINamespace = "\root\CIMV2"
strWMIQuery = "SELECT * FROM Win32_TimeZone"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace)
Set colItems = objWMIService.ExecQuery(strWMIQuery)
For Each objItem In colItems
WScript.Echo objItem.Caption
Next
Và đây là kết quả chạy của script:
C:\scripts>cscript DisplayTimeZone.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
(GMT-06:00) Central Time (US & Canada)
Hãy xem script này hoạt động như thế nào. Đầu tiên, bạn có thể thấy chúng dựa trên rất nhiều các script đã được tạo ở trên. Nói cách khác, chúng ta bắt đầu bằng cách kết nối WMI, dùng lệnh sau:
Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace)
Nhưng lệnh tiếp theo là mới:
Set colItems = objWMIService.ExecQuery(strWMIQuery)
Điều chúng ta thực hiện ở đây là thực thi một truy vấn trên WMI để thu thập thông tin từ nó. Truy vấn được định nghĩa trước đó, dùng lệnh sau:
strWMIQuery = "SELECT * FROM Win32_TimeZone"
Câu lệnh SELECT theo kiểu cấu trúc SQL này sẽ trả ra tất cả (dấu hoa thị) những gì nhà cung cấp Win32_TimeZone có cho chúng ta và lưu trữ kết quả trong một tập hợp có tên colItems. Sau đó, lặp lại thao tác với từng đối tượng trong tập hợp (chỉ có một đối tượng được trả về bằng truy vấn) và hiển thị thuộc tính Caption của đối tượng, là xâu ký tự như bên dưới:
(GMT-06:00) Central Time (US & Canada)
Hãy thử nghiệm bài tập này
Chúng ta sẽ nghiên cứu sâu hơn về WMI scripting trong những bài sau, còn bây giờ hãy thử nghiệm một bài tập nhỏ. Copy nội dung của script DisplayTimeZone.vbs ở trên vào Notepad (nhớ tắt Word Wrap) và ghi nó lại dưới tên file PageFile.vbs. Bây giờ, thay đổi một dòng trong script (thực ra là một phần nhỏ của dòng) để khi script chạy, nó sẽ hiển thị đường dẫn và tên pagefile của hệ thống thay vì múi giờ. Mẹo: Tìm trên MSDN để có thêm thông tin về lớp Win32_PageFile. Chúng tôi sẽ đưa ra câu trả lời cho thử nghiệm này ở phần tiếp theo của loạt bài.
(Theo quantrimang.com)