Jump to content

Multiple Domains, WMI and Alternate Credentials


Bob Hoss
 Share

Recommended Posts

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
Link to comment
Share on other sites

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
Link to comment
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?

Link to comment
Share on other sites

  • Moderators

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.

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.

Link to comment
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
Link to comment
Share on other sites

  • 4 years later...

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 ??

Link to comment
Share on other sites

  • Moderators

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

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...