Sign in to follow this  
Followers 0
Bob Hoss

Multiple Domains, WMI and Alternate Credentials

9 posts in this topic

First time poster - so be nice please :P

I generally don't think about posting my code, but I think this one could be helpful. I developed a script to push a patch via WMI over 8 domains (same forest) utilizing alternate credentials when needed. Anyway - I hope someone gets some use out of this. I did have us entering credentials instead of reading from a file (they are now stored in a text file username@domain.com,password) but if it bombed you had to type them all back in again. Also, I hard coded the servers list file name - but that could easily be changed. The servers should be in a plain text file, one per line.

The script does the following:

Tries To Ping the Server - If no ping - log

If ping good - Tries to Connect to WMI on the remote server using current credentials.

If that doesn't work - it goes through a list of potential credentials per machine.

If No WMI connect - log

If WMI connects - Then check to make sure it's not already patched - if so - log it

If not patched - kick off remote process for patch from UNC on server where share is WIDE open.

The Patch Installs - and forces a reboot of the machine

Once the machine reboots - we log install successful

#include <file.au3>
#include <Array.au3>
#include <Date.au3>

;Create Vars
     ;Var For Counting Through The PassWord Array
     $i = 0

     ;Var For Reboot
     $strNoReboot = ""

     ;Var For Counting Servers
     $strServerCount = 1

     ;Title Text For Status Screens
     $strTitleText = "Installing Patch On "

;Read Servers List Into An Array
Dim $arrServers[1]

_FileReadToArray(@ScriptDir &"\wmi.txt", $arrServers)
$strServersTotal = $arrServers[0]
_ArrayDelete($arrServers,0)

;Create Log File With a Time Date Stamp Where End User Chose Folder At
$strLogFileName = "MS06-040-" &@MON &"-" &@MDAY &"-" &@YEAR &"-" &@HOUR &@MIN &@SEC &".csv"
$strLogFilePath = @ScriptDir &"\" &$strLogFileName
$filLogFile = FileOpen($strLogFilePath, 1)
FileWriteLine($filLogFile, "Server_Name,Status")

;Get A List Of Credentials To Try
Dim $arrCredentials[1][2]

$x = 0

$filPassWords = FileOpen(@ScriptDir &"\passwords.txt",0)

While 1
     $line = FileReadLine($filPassWords)
      If @error = -1 Then ExitLoop
     If $x >=1 Then
          ReDim $arrCredentials[$x+1][2]
     EndIf
     $arrTemp = StringSplit($line, ",")
     $arrCredentials[$x][0] = $arrTemp[1]
     $arrCredentials[$x][1] = $arrTemp[2]
     $x = $x + 1
Wend

;Create The WbemScripting.SWbemLocator Object
$objSWbemLocator = ObjCreate("WbemScripting.SWbemLocator")

;Error Handling For Com Object
$objError = ObjEvent("AutoIt.Error","WMI_Connect_Error")

;Go Through Each Server In List Try To Install MS06-040 Patch
For $strComputer in $arrServers
     SplashTextOn($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal, @CR &"Pinging Server...", 400, 125, 700 ,600, 18)

     ;Ping Server
     $strPing = Ping($strComputer,250)

     ;Ping Good - Try To Connect To WMI
     If $strPing Then
          ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"Trying To Connect To WMI With Current Credentials...")

          ;Try Logged On Credentials First
          $objWMIService = $objSWbemLocator.ConnectServer($strComputer, "root\cimv2")

          ;Loop Through Credentials List And See If We Can Connect To Server With Alt. Credentials
          Do
               ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"Trying To Connect To WMI With Alternate Credentials...")
               If $i = Ubound($arrCredentials)-1 Then ExitLoop
               Global $strUserName = $arrCredentials[$i][0]
               Global $strPassWord = $arrCredentials[$i][1]
               $i = $i + 1
               If $strUserName = "administrator" Then
                    Global $objWMIService = $objSWbemLocator.ConnectServer($strComputer, "root\cimv2", $strcomputer &"\" &$strUserName, $strPassword)
               Else
                    Global $objWMIService = $objSWbemLocator.ConnectServer($strComputer, "root\cimv2", $strUserName, $strPassword)
               EndIf
          Until IsObj($objWMIService)
     ;Ping Bad - Log It
     Else
          ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Couldn't Ping Server - Writing To Log")
          FileWriteLine($filLogFile, $strComputer &",Couldn't Ping,Couldn't Ping,Couldn't Ping")
          ContinueLoop
     EndIf

     ;Connected to WMI O.K.
     If IsObj($objWMIService) Then
          ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"WMI Connected O.K." &@CR &"Querying Server For OS Details...")
          ;Get OS Details
          $colWIN32OS = $objWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem")
          For $objItem in $colWIN32OS
               $strOS = $objItem.Caption
               $strSP = $objItem.ServicePackMajorVersion
          Next

          ;Change Caption Name As Needed
          Select
               ;Windows 2000
               Case StringInStr($strOS, "2000")
                    $strOS = "Windows 2000"
                    $strPatchPath = "\\<ServerName>\<Share>\Windows2000-KB921883-MS06-040.EXE /quiet /log:c:\ms06040.txt /forcerestart /forceappsclose"
               ;Windows XP
               Case StringInStr($strOS, "XP")
                    $strOS = "Windows XP"
                    $strPatchPath = "\\<ServerName>\<Share>\WindowsXP-KB921883-x86-ENU.exe /quiet /log:c:\ms06040.txt /forcerestart /forceappsclose"
               ;Windows 2003
               Case StringInStr($strOS, "2003")
                    $strOS = "Windows 2003"
                    $strPatchPath = "\\<ServerName>\<Share>\Windows2003-KB921883-MS06-040.exe /quiet /log:c:\ms06040.txt /forcerestart /forceappsclose"
          EndSelect

          ;How To Handle Win2K With Wrong SP
          If $strOS = "Windows 2000" AND $strSP <> "4" Then
               ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"WMI Connected O.K." &@CR &"Server Is At Wrong Service Pack - Writing To Log.")
               FileWriteLine($filLogFile,$strComputer &",Windows 2000 Server - Incorrect Service Pack Level - Did Not Patch")
               ContinueLoop
          EndIf

          ;Find Out If Patch Already Installed
          ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"WMI Connected O.K." &@CR &"OS Version is " &$strOS &@CR &"Checking To See If Patch Is Already Installed...")
          $colWin32Hotfix = $objWMIService.ExecQuery("SELECT * FROM Win32_QuickFixEngineering Where ServicePackInEffect = 'KB921883'")
          For $objItem In $colWin32Hotfix
               If $objItem.ServicePackInEffect Then
                    ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"WMI Connected O.K." &@CR &"OS Version is " &$strOS &@CR &"Patch Is Already Installed - Writing To Log.")
                    FileWriteLine($filLogFile,$strComputer &",Already Patched")
                    ContinueLoop(2)
               EndIf
          Next

          ;Install Patch
          ;Set Impersonation Level 3
          $objWMIService.Security_.ImpersonationLevel = 3

          ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"Connected To WMI" &@CR &"OS Version is " &$strOS &@CR &"Installing Patch...")
          ;Connect to WMI and Start Patch From UNC
          $objProcess = $objWMIService.Get("Win32_Process")
;          msgbox(0,"t","Would be installing now.")
          $objProcess.Create($strPatchPath)

          ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"Connected To WMI" &@CR &"OS Version is " &$strOS &@CR &"Patch Installation Initiated at " &_NowTime())
          $begin = TimerInit()

          Do
               $StrRebootPing = Ping($strComputer)
               Sleep(3000)
               $dif = TimerDiff($begin)
               If $dif >= 300000 Then
                    $strWait = msgbox(1,"Question....","You've waited over 5 minutes for " &$strComputer &" to reboot - would you like to wait another 5?")

                    ;Exit Loop And Go To Next Server
                    If $strWait = 2 Then
                         $strNoReboot = "Did Not Reboot."
                         ExitLoop
                    EndIf

                    ;Wait Again
                    If $strWait = 1 Then
                         $begin = TimerInit()
                         ContinueLoop
                    EndIf
               EndIf
          Until $StrRebootPing = 0

          ;Server Never Rebooted - User Skipped Waiting To Move To Next Server In List
          If $strNoReboot = "Did Not Reboot." Then
                         ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"Connected To WMI" &@CR &"OS Version is " &$strOS &@CR &"Patch May Not Have Installed - Server Did Not Reboot.  Writing To Log.")
                         FileWriteLine($filLogFile,$strComputer &",Did Not Reboot - Needs Checked.")
                         ContinueLoop
          EndIf

          ;Rebooted and All is Well
          If $strNoReboot = "" Then
               ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"Connected To WMI" &@CR &"OS Version is " &$strOS &@CR &"Patch Installed - Server Rebooted.  Writing To Log.")
               FileWriteLine($filLogFile,$strComputer &",Installation Sucessful.")
          EndIf

     EndIf

     ;Could Not Connect To WMI
     If NOT IsObj($objWMIService) Then
          ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"Couldn't Connect To WMI - Writing To Log")
          FileWriteLine($filLogFile,$strComputer &",Couldn't Connect To WMI,Couldn't Connect To WMI,Couldn't Connect To WMI")
     EndIf

     ;Reset Vars For Next Machine In List
     $i = 0
     $strNoReboot = ""

     ;Add To Count
     $strServerCount = $strServerCount + 1
Next

;Turn Off SplashScreen
SplashOff()

;Close Log File
FileClose($filLogFile)

;Quit Script
Exit

;Error Handling Function For WbemScripting.SWbemLocator Object - Forces Return To Code Instead Of Bombing Out
Func WMI_Connect_Error()
     Return("Caught Error")
EndFunc

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

First time poster - so be nice please :P

;Ping Good - Try To Connect To WMI
     If $strPing Then
          ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"Trying To Connect To WMI With Current Credentials...")

shouldnt $strPing be compaired to something?

Edited by blitzkrg

Share this post


Link to post
Share on other sites

I believe it compares as true and then there's an else statement to comply with the no ping. Please correct if wrong - thanks for the note!

;Ping Good - Try To Connect To WMI
     If $strPing Then
          ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"Trying To Connect To WMI With Current Credentials...")

shouldnt $strPing be compaired to something?

Share this post


Link to post
Share on other sites

I believe it compares as true and then there's an else statement to comply with the no ping. Please correct if wrong - thanks for the note!

You are correct.

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

You are correct.

i learn something new everyday :P

Share this post


Link to post
Share on other sites

Found a Bug - posting the fix...

If NOT IsObj($objWMIService) Then
               Do
                    ControlSetText($strTitleText &$strComputer &"  " &$strServerCount &"\" &$strServersTotal,"","Static1", "Ping Status - O.K." &@CR &"Trying To Connect To WMI With Alternate Credentials...")
                    If $i = Ubound($arrCredentials)-1 Then ExitLoop
                    Global $strUserName = $arrCredentials[$i][0]
                    Global $strPassWord = $arrCredentials[$i][1]
                    $i = $i + 1
                    If $strUserName = "administrator" or $strUserName = "administrato" Then
                         Global $objWMIService = $objSWbemLocator.ConnectServer($strComputer, "root\cimv2", $strcomputer &"\" &$strUserName, $strPassword)
                    Else
                         Global $objWMIService = $objSWbemLocator.ConnectServer($strComputer, "root\cimv2", $strUserName, $strPassword)
                    EndIf
               Until IsObj($objWMIService)
          EndIf

Share this post


Link to post
Share on other sites

I am trying to do something similar but only on one domain.. I have never used WMI before i read this post.. I was playing around with autoit / wmi and have been able to retrieve system info but have yet to try to install a patch remotely.. Is there any advice to get started ??

Share this post


Link to post
Share on other sites

myk3,

I seriously doubt you will get a reply from a thread that has been dead for over 4 years! :P

Just search the forum (the facility is at top right of the page) for WMI - there are lots of scripts out there. If you do not find anything that answers your specific question then start your own topic in the General Help forum. :x

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0