Sunday, January 27, 2008

local admin password change script

ok, so from time to time an admin leaves and you need to change local admin on a bunch of computers... annoying how ms doesn't let you just click to do it for the domain via AD...

so i had to do this recently, and after searching the net for script examples, i put this together. basically, it lets you update the local admin accout (or any acct, note that "administrator" isn't a variable in the script like it should be ;). you can do it for a domain, or for an ou, or for a group of boxes...

the way i used it was to run it on a domain, and then use grep, sed, awk, and wc to pull out the failed boxes, and then plug them back into the script as a list of individual boxes. you can do this a number of times and catch stragglers (boxes that are ooto or off), and also end up w/ a list of machines which still have the old password...

so anywho, it was useful for me, hopefully it will be useful for other ppl... enjoy...

btw, blogger totally butchered my whitespacing and all of that... sry...


''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''
''
'' Local Admin Password Update script by rwnin
''
'' Update the local admin password on a domain
'' or group of computers.
''
''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''
option explicit
on error resume next

const forWriting = 2
const forAppending = 8

dim objUpdates
dim objLocalUser
dim objFSO
dim objLog
dim objItem

dim i
dim numUpdates

dim errText
dim errLog
dim newPassword
dim strBox

dim arrHostnames()
dim tempArr

newPassword = "y3r#n3w#p4ss#h3r3"

errLog = "pupdate_log.txt"

'' prep our logging
set objFSO = CreateObject("Scripting.FileSystemObject")

if (objFSO.FileExists(errLog) = false) then
set objLog = objFSO.CreateTextFile(errLog)
end if

set objLog = nothing
set objLog = objFSO.OpenTextFile(errLog, forWriting, true)
set objFSO = nothing

objLog.WriteLine("Executing at: " & date & " " & time)

'' Kludge Alert:
''
'' for pulling hostnames, the .Count method isn't implemented, n .PropertyCount
'' method seems to return the count of all of the objects in the collection, not the
'' filtered ones... so i decided to iterate once to count and then again to collect the
'' names. it could be done in a single loop, but then you'd have to redim (right?) for
'' each iteration, and that seems more expensive than just doing 2 loops...
''
'' also, for querying via OU, i know you can set the scope to subtree w/ a straight
'' query, but i haven't figured out how to do it w/ the getobject call... so, atm it
'' will only query the OU you specify. if you're doing sub OUs you have to say:
'' OU=subou, OU=mainou, DC=etc etc etc... i should update it, but i'm bein lazy...
''

''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''
'' uncomment for domain query
''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''
'set objUpdates = GetObject("WinNT://your.addomain.tld,domain")
'objUpdates.Filter = Array("Computer")
'numUpdates = 0
'for each objItem in objUpdates
' numUpdates = numUpdates + 1
'next
'redim arrHostnames(numUpdates)
'i = 0
'for each objItem in objUpdates
' arrHostnames(i) = objItem.Name
' i = i + 1
'next


''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''
'' _OR_ uncomment for OU query
''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''
'set objUpdates = GetObject("LDAP://OU=subsubou, OU=subou, OU=ou, DC=your, DC=addomain, DC=tld")
'objUpdates.Filter = Array("Computer")
'numUpdates = 0
'for each objItem in objUpdates
' numUpdates = numUpdates + 1
'next
'redim arrHostnames(numUpdates)
'i = 0
'for each objItem in objUpdates
' arrHostnames(i) = objItem.CN
' i = i + 1
'next

''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''
'' _OR_ uncomment to manually define a list
''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''
'' stupid vbs doesn't let you copy arrays to dim'd variables
'numUpdates = 3
'redim arrHostnames(numUpdates)
'tempArr = Array("box1", "box2", "box3")
'for i = 0 to (numUpdates - 1)
' arrHostnames(i) = tempArr(i)
'next


'' now we loop through and try our updates. timeout on hosts that don't respond can
'' be approx 20 sec in my experience, so give this some time...
for i = 0 to (numUpdates - 1)

'' build the string and get the object...
set objLocalUser = GetObject("WinNT://" & arrHostnames(i) & "/Administrator")
if (err.number <> 0) then
select case Err.Number
case -2147024843
errText = arrHostnames(i) & ": Unable to connect to host"
case else
errText = arrHostnames(i) & ": Unknown error (num: " & err.number & ") occured"
end select
err.clear
objLog.WriteLine(errText)
else
'' attempt to set the password
objLocalUser.SetPassword(newPassword)
if (err.number <> 0) then
select case Err.Number
case 424
errText = arrHostnames(i) & ": Unable to connect to host"
case else
errText = arrHostnames(i) & ": Unknown error (num: " & err.number & ") occured"
end select
err.clear
objLog.WriteLine(errText)
else
objLog.WriteLine("Updated " & arrHostnames(i))
end if
end if
next

objLog.WriteLine("Completed...")
objLog.Close
set objLog = nothing
set objLocalUser = nothing
set objUpdates = nothing

No comments: