580 likes | 852 Views
WMI 實務應用範例. 曹祖聖 台灣微軟資深講師 jimycao@syset.com http://teacher.allok.com.tw MCP, MCP+I, MCSA, MCSE, MCDBA, MCAD, MCSD, MCT, MVP. 上一次的作業. 撰寫一個指令碼 功能 監控來自其它電腦的網路檔案存取 將事件記錄下來 提示 使用 WQL 事件過濾 從 Win32_Share 開始著手,檢視相關的關連類別 . 解答. Set objService = GetObject("winmgmts:\ServerA")
E N D
WMI 實務應用範例 曹祖聖 台灣微軟資深講師 jimycao@syset.com http://teacher.allok.com.tw MCP, MCP+I, MCSA, MCSE, MCDBA, MCAD, MCSD, MCT, MVP
上一次的作業 • 撰寫一個指令碼 • 功能 • 監控來自其它電腦的網路檔案存取 • 將事件記錄下來 • 提示 • 使用 WQL 事件過濾 • 從 Win32_Share 開始著手,檢視相關的關連類別
解答 Set objService = GetObject("winmgmts:\\ServerA") Do While True Set colSettings = objService.ExecQuery( _ "Select * from Win32_ServerConnection") For Each obj in colSettings WScript.Echo obj.ComputerName & "," & obj.UserName Next WScript.Sleep(10000) Loop
先講在前頭 … • 這一次 … • 我不再重新講什麼是 WMI, CIM, WQL, … 了 • 因為範例太多,時間不夠 • 我會一直講範例 • 一直講、一直講、… 講到你受不了起來抗議為止 • 您要有心理準備 … • 接下來有一大堆的程式碼,近百個範例 • 當然我會解釋的,別擔心 • 可是每個範例,我只有 1 分多鐘可以用,慘 ~~~ • 大家深呼吸一口氣 … 讓我們開始吧 …
大綱 • 使用者與群組管理 • Active Directory ADO Provider • 服務啟動的帳號與密碼 • 電腦、網域、工作群組 • 其它
大綱 • 使用者與群組管理 • Active Directory ADO Provider • 服務啟動的帳號與密碼 • 電腦、網域、工作群組 • 其它
取得目前使用者的 LDAP 路徑 Set objADSysInfo = CreateObject("ADSystemInfo") WScript.Echo "目前使用者 LDAP 路徑:" & _ objADSysInfo.UserName
取得目前使用者所屬的群組 Set objADSysInfo = CreateObject("ADSystemInfo") strUser = objADSysInfo.UserName S = strUSer & vbCrLf & "屬於以下群組:" & vbCrLf Set objUser = GetObject("LDAP://" & strUser) If IsArray(objUser.MemberOf) Then For Each group in objUser.MemberOf Set objGroup = GetObject("LDAP://" & group) S = S & objGroup.CN & vbCrLf Next Else S = S & objUser.MemberOf End If WScript.Echo S
取得目前使用者所屬的群組 Set objADSysInfo = CreateObject("ADSystemInfo") strUser = objADSysInfo.UserName S = strUSer & vbCrLf & "屬於以下群組:" & vbCrLf Set objUser = GetObject("LDAP://" & strUser) For Each group in objUser.Groups S = S & group.CN & vbCrLf Next WScript.Echo S
取得組織單位下使用者的群組 Set objUsers = GetObject("LDAP://OU=RD,DC=mcg,DC=com") objUsers.Filter = Array("User") For Each obj In objUsers S = obj.AdsPath & vbCrLf & "屬於以下群組:" & vbCrLf For Each group In obj.Groups S = S & group.CN & vbCrLf Next WScript.Echo S Next
取得某一群組的成員 Set obj = GetObject( _ "LDAP://CN=RdManagers,OU=RD,DC=mcg,DC=com") S = obj.AdsPath & vbCrLf & "的成員:" & vbCrLf For Each mem In obj.Members S = S & mem.CN & vbCrLf Next WScript.Echo S
使用者是否為本機系統管理員 Set objNetwork = CreateObject("Wscript.Network") strComputer = objNetwork.ComputerName strUser = objNetwork.UserName Set objGroup = GetObject( _ "WinNT://" & strComputer & "/Administrators") For Each objUser in objGroup.Members If objUser.Name = strUser Then Wscript.Echo strUser & " 是本機系統管理員。" End If Next
新增使用者到本機群組 strComputer = "ServerC" strDomain = "MCG" strUser = "user1" Set objGroup = GetObject( _ "WinNT://" & strComputer & "/Administrators") Set objUser = GetObject( _ "WinNT://" & strDomain & "/" & strUser) objGroup.Add(objUser.ADsPath)
變更使用者密碼 • 變更本機使用者的密碼 • 變更網域使用者的密碼 Set objUser = GetObject("WinNT://ServerC/user1") objUser.SetPassword("Pa$$word!") Set objUser = GetObject( _ "LDAP://CN=user1,OU=RD,DC=mcg,DC=com") objUser.SetPassword("Pa$$word!")
大綱 • 使用者與群組管理 • Active Directory ADO Provider • 服務啟動的帳號與密碼 • 電腦、網域、工作群組 • 其它
Active Directory 是個資料庫 ! • Active Directory 本來就是個資料庫 • 所以 … • 可以用 ADO 來存取它 ?! • 是的 ! • 透過 Active Directory ADO Provider • Provider 名稱: ADsDSOObject • 連線字串: Active Directory Provider
建立 AD ADO Provider 連線 • 使用 Windows 整合驗證 Set objConnection = CreateObject("ADODB.Connection") objConnection.Provider = "ADsDSOObject" objConnection.Open "Active Directory Provider" Set objCommand = CreateObject("ADODB.Command") Set objCommand.ActiveConnection = objConnection
建立 AD ADO Provider 連線 • 使用指定使用者與密碼 Set objConnection = CreateObject("ADODB.Connection") objConnection.Provider = "ADsDSOObject" objConnection.Properties("User ID") = "Administrator" objConnection.Properties("Password") = “Pa$$word!" objConnection.Properties("Encrypt Password") = TRUE objConnection.Properties("ADSI Flag") = 1 objConnection.Open "Active Directory Provider" Set objCommand = CreateObject("ADODB.Command") Set objCommand.ActiveConnection = objConnection
建立 AD ADO Provider 連線 • 連線屬性 (Properties)
PageSize 屬性 • 預設只會傳回前 1000 筆資料 • 解決方案,設定 PageSize 屬性 • AD ADO Provider 會每次傳回 500 筆資料 • 然後再傳回下 500 筆資料 • 一直到所有資料全部取回為止 objCommand.Properties("Page Size") = 500
Searchscope 屬性 • AD 是樹狀結構的資料庫 • 必須設定搜尋的範圍 • 使用 Searchscope 屬性: Const ADS_SCOPE_BASE = 0 Const ADS_SCOPE_ONELEVEL = 1 Const ADS_SCOPE_SUBTREE = 2 objCommand.Properties(“Searchscope") = _ ADS_SCOPE_BASE
Sort On屬性 • 設定排序方式 • 不能做一層以上的排序 objCommand.Properties("Sort On") = "SN"
查詢語法 • 設定 Command 物件的 CommandText 屬性 • 類似存取資料庫的 SQL 語法 • 注意大小寫,而且不能用 SELECT * FROM … • 但是,別想太多 … • 你不能用 INSERT, UPDATE, DELETE 語法 ! objCommand.CommandText = _ "SELECT Name FROM 'LDAP://DC=mcg,DC=com' " & _ "WHERE objectCategory='user'"
查詢語法 (範例) objCommand.CommandText = _ "SELECT CN, Department, Title FROM " & _ "'LDAP://DC=mcg,DC=com' " & _ "WHERE objectCategory='user'" objCommand.CommandText = _ "SELECT CN, Department, Title FROM " & _ "'LDAP://dc=fabrikam,dc=com' " & _ "WHERE objectCategory='user' " & _ "OR objectCategory='computer'"
objectClass vs. objectCategory • objectClass=‘user’ • 不只會傳回所有使用者帳戶物件 • 還會傳回所有繼承 User 類別的子類別的物件
列出網域所有使用者 objCommand.CommandText = _ "SELECT Name FROM 'LDAP://DC=mcg,DC=com' " & _ "WHERE objectCategory='user'" Set RS = objCommand.Execute Do While Not RS.EOF S = S & RS("Name") & vbCrLf RS.MoveNext Loop WScript.Echo S
使用者帳戶所屬的組織單位 objCommand.CommandText = _ "SELECT distinguishedName FROM 'LDAP://DC=mcg,DC=com' " & _ "WHERE objectCategory='user' " & _ "AND sAMAccountName='user1'" Set RS = objCommand.Execute Do Until RS.EOF strDN = RS("distinguishedName") arrPath = Split(strDN, ",") intLength = Len(arrPath(1)) intNameLength = intLength - 3 Wscript.Echo Right(arrPath(1), intNameLength) RS.MoveNext Loop ' RS("distinguishedName").Value --> CN=user1,OU=RD,DC=mcg,DC=com ' arrPath(1) --> OU=RD
組織單位內使用者帳戶的數目 Const ADS_SCOPE_ONELEVEL = 1 objCommand.Properties("Searchscope") = ADS_SCOPE_ONELEVEL objCommand.CommandText = _ "SELECT Name FROM 'LDAP://OU=RD,DC=mcg,DC=com' " & _ "WHERE objectCategory='user'" Set RS = objCommand.Execute Wscript.Echo "使用者帳戶數目 = " & RS.RecordCount
大綱 • 使用者與群組管理 • Active Directory ADO Provider • 服務啟動的帳號與密碼 • 電腦、網域、工作群組 • 其它
列出所有服務的啟動帳號 Set objService = GetObject("winmgmts:") Set objCol = objService.ExecQuery("SELECT * FROM Win32_Service") For Each obj In objCol S = S & obj.DisplayName & " (" & obj.StartName & " )" & vbCrLf Next WScript.Echo S
列出某一帳號啟動的服務 UserName = ".\\SqlAdmin" ' WQL 語法中 \ 符號要用 \\ 代替 Set objService = GetObject("winmgmts:") Set objCol = objService.ExecQuery( _ "SELECT * FROM Win32_Service WHERE " & _ StartName='" & UserName & "'") S = "以下都是用 " & UserName & " 帳戶啟動的服務:" & vbCrLf For Each obj In objCol S = S & obj.DisplayName & vbCrLf Next WScript.Echo S
修改某帳號啟動服務的密碼 OldUserName = ".\\SqlAdmin" ' WQL 語法中 \ 符號要用 \\ 代替 NewUserName = ".\jimycao" NewPassword = "Pa$$word!" Set objService = GetObject("winmgmts:") Set objCol = objService.ExecQuery( _ "SELECT * FROM Win32_Service WHERE " & _ StartName='" & OldUserName & "'") For Each obj In objCol If NewUserName = "" Then obj.Change , , , , , , , NewPassword Else obj.Change , , , , , , NewUserName, NewPassword End If S = S & obj.DisplayName & vbCrLf Next
大綱 • 使用者與群組管理 • Active Directory ADO Provider • 服務啟動的帳號與密碼 • 電腦、網域、工作群組 • 其它
修改電腦名稱 NewComputerName = "T40" Set objService = GetObject("winmgmts:{(shutdown)}") Set objCols = objService.InstancesOf("Win32_ComputerSystem") For Each obj In objCols obj.Rename NewComputerName Next Set objCols = objService.InstancesOf("Win32_OperatingSystem") For Each obj In objCols obj.Reboot() Next
加入網域 NewDomainName = "mcg.com" UserName = "Administrator" Password = "Pa$$word!" OU = "OU=Sales,DC=mcg,DC=com" Set objService = GetObject("winmgmts:{(shutdown)}") Set objCols = objService.InstancesOf("Win32_ComputerSystem") For Each obj In objCols obj.JoinDomainOrWorkgroup NewDomainName, _ Password, UserName, OU, 1 + 2 + 16 Next WScript.Echo "電腦已經加入 " & NewDomainName & " 網域。"
加入網域 – FJoinOptions 參數 • 第 0 位元 (1) - 加入網域, 如果網域不存在,電腦會加入工作群組 • 第 1 位元 (2) - 建立電腦帳戶 • 第 2 位元 (4) - 刪除電腦帳戶 • 第 4 位元 (8) - Win9X 升級 • 第 5 位元 (16) - 即使已在網域中,還是要加入網域 • 第 6 位元 (32) - 未設定安全的加入 • 第 7 位元 (64) - 傳入電腦密碼, 這個選項只能用在未設定安全的加入。 • 第 8 位元 (128) - 順延 SPN 組合,指定在電腦物件上寫入SPN 和 DnsHostName 屬性的操作應該順 延到加入後的重新命名。 • 第 18 位元 - 安裝啟動 - 在安裝時啟動 API。
脫離網域 UserName = "MCG\Administrator" Password = "Pa$$word!" Set objService = GetObject("winmgmts:{(shutdown)}") Set objCols = objService.InstancesOf("Win32_ComputerSystem") For Each obj In objCols obj.UnjoinDomainOrWorkgroup Password, UserName, 4 Next WScript.Echo "電腦已經脫離網域,並加入與網域同名的工作群組。"
加入工作群組 NewWorkGroupName = "WORKGROUP" Set objService = GetObject("winmgmts:{(shutdown)}") Set objCols = objService.InstancesOf("Win32_ComputerSystem") For Each obj In objCols obj.JoinDomainOrWorkgroup NewWorkGroupName, _ "Pa$$word!", "MCG\Administrator" Next WScript.Echo "電腦已經加入工作群組: " & NewWorkGroupName
強迫登出使用者 Set objWMIService = GetObject("winmgmts:\\ServerC") Set objCol = objWMIService.ExecQuery _ ("Select * from Win32_OperatingSystem") For Each obj In objCol obj.Win32Shutdown 0 ' 0 表示登出 Next
強迫鎖定電腦 Set objShell = CreateObject("Wscript.Shell") objShell.Run "%windir%\System32\rundll32.exe " & _ "user32.dll, LockWorkStation" Const OverwriteExisting = TRUE Set objShell = CreateObject("Wscript.Shell") objShell.Run "cmd.exe /c copy c:\lock.vbs \\ServerC\C$\scripts\" Set objService = GetObject("winmgmts:\\ServerC") Set obj = objService.Get("Win32_Process") obj.Create "cscript c:\scripts\lock.vbs", null, null, intProcessID
大綱 • 使用者與群組管理 • Active Directory ADO Provider • 服務啟動的帳號與密碼 • 電腦、網域、工作群組 • 其它
測試網路連線 (Ping) strComputer = "192.168.99.1" Set objWMIService = GetObject("winmgmts:") Set colItems = objWMIService.ExecQuery( _ "Select * from Win32_PingStatus " & _ "Where Address='" & strComputer & "'") For Each obj in colItems If obj.StatusCode = 0 Then WScript.Echo "成功 !" Else WScript.Echo "失敗 !" End If Next
依照規則變更檔名 ' 將 C:\Photos 資料夾中的 SANY4958.JPG 更名為 Boston_4958.JPG Set objService = GetObject("winmgmts:") Set colFiles = objService.ExecQuery( _ "ASSOCIATORS OF {Win32_Directory.Name='C:\Photos'} " & _ "WHERE ResultClass=CIM_DataFile") For Each objFile In colFiles strEnd = Right(objFile.Name, 8) ' 取得最後 8 個字 strNewName = objFile.Drive & objFile.Path & "Boston_" & strEnd objFile.Rename strNewName Next