Delete multiple computer objects from Active Directory
Team,
I already spent many hours searching for a script which can pick the list of the computer objects from a text file and delete them from an Active Directory, got multiple scripts on internet to delete a single computer object but cant find one which can pick the list from the text file and delete those at one go and if possible create a log after deleting the computer account from the active directory for verification.
A Vbscript or a bat file will do.
Please help guys as this question is raised by many needy people now.
Thanks
Inderjit
Answers
- Hi Inderjit,
The easiest would be to run this from the CLI and pipe the output to a text file (my example below assumes you've named the script del-computers.vbs and you are piping your output to the results.log log file):
cscript del-computers.vbs > results.log
Regards,
Salvador Manaois III
MCITP | Enterprise & Server Administrator
MCSE MCSA MCTS(x5) CIWA C|EH
My Blog: Bytes and Badz
My Shots: View My PhotoStream- Marked As Answer byIJSingh Thursday, July 02, 2009 11:55 AM
- Thanks Matthew,
Thats perfectly what i need, i am now able to delete 100 objects at one Go....Thanks a lot.
To Salvador,
when i ran the vbscript you pasted above i got an error message saying "Error deleting computername1", i think i need to specify what OU these computers belongs to because i got a big web of OU's in our AD..is that so?
BTW i do changed the file name to computers.txt and the domain information as well.
Thanks for helping me guys
Inderjit- Marked As Answer byIJSingh Thursday, July 02, 2009 11:55 AM
All Replies
Hey
There are multiple ways to do this...you could script it or use the tools microsoft already provides and use these to create a batch file for mass deletion...for example
dsquery computer -samid "desktop1" | dsrm computer
That command should search AD for the distinguished name of the computer account "desktop1" then pass the result to the dsrm utility to delete the computer account....or you could script it if you'd prefer more error checking and logging. Here are a few links...
http://www.microsoft.com/technet/scriptcenter/resources/qanda/jun07/hey0628.mspx
http://technet.microsoft.com/en-us/library/cc730720(WS.10).aspx
http://technet.microsoft.com/en-us/library/cc754624.aspx#BKMK_cmd
You'd have to perform an ldap query for the distinguished Name of each computer account read from a text file, find it then delete it. Try the default tools microsoft provide and if that doesn't do the job for you then post a reply and i'll cut and paste a few functions into a script for you.
Cheers
Matt :)- Hi Inderjit,
You can try the following:
Const SourceFile = ".\computers.ini" On Error Resume Next Set objFSO = Wscript.CreateObject("Scripting.FileSystemObject") Set oSourceFile = objFSO.OpenTextFile(SourceFile, 1) While oSourceFile.AtEndOfStream <> True strComputer = oSourceFile.ReadLine set objComputer = GetObject("LDAP://CN=" & strComputer & _ ",CN=Computers,DC=fabrikam,DC=com") objComputer.DeleteObject (0) If Err.Number <> 0 Then Wscript.Echo "Error deleting " & strComputer & "." Err.Clear Else Wscript.Echo strComputer & " was succesfully deleted." End If Wend
Adding a logging feature to this should be very straightforward. =)
Regards,
Salvador Manaois III
MCITP | Enterprise & Server Administrator
MCSE MCSA MCTS(x5) CIWA C|EH
My Blog: Bytes and Badz
My Shots: View My PhotoStream- Edited bySalvador Manaois IIIModeratorThursday, July 02, 2009 9:17 AMtypo
Thanks Matt, I will check out the links and will reply if need help, but if you can please spend some time to create a script as well that will going to help a lot of needy guys, i know for sure there are IT Admin guys are there somewhere who don’t know much in the scripting world (and honestly I am one of them) so for kids like us who know how to run mouse click and press delete only i would request you to prepare one script for us and save our job.
Appreciate your help!
Thanks
InderjitThanks Salvador,
I don’t know much in the scripting world so would need your help to add the login feature what you are mentioning in your answer, if you can add that as well and help me to get the final version of the script which I can use specifying the path for the text file that will be very helpful.
Thanks
Inderjit- Hi Inderjit,
The easiest would be to run this from the CLI and pipe the output to a text file (my example below assumes you've named the script del-computers.vbs and you are piping your output to the results.log log file):
cscript del-computers.vbs > results.log
Regards,
Salvador Manaois III
MCITP | Enterprise & Server Administrator
MCSE MCSA MCTS(x5) CIWA C|EH
My Blog: Bytes and Badz
My Shots: View My PhotoStream- Marked As Answer byIJSingh Thursday, July 02, 2009 11:55 AM
- Hi Inderjit
There is a syntax error in the previous command i posted. The actual command to delete a computer account from active directory (assuming the user running the command has permissions to do so) is:
dsquery computer -samid computerName1$ | dsrm -noprompt
where "computerName" is the sAMAccountName property of the computer account for example "desktop1"...make sure you include the $ sign after the computer name. So you could quite easily just put the computer accounts you want to delete into one big batch file and run that
dsquery computer -samid computerName1$ | dsrm -noprompt
dsquery computer -samid computerName2$ | dsrm -noprompt
dsquery computer -samid computerName3$ | dsrm -noprompt
...etc..etc
Anyway hope that helps
Cheers
Matt :) - Thanks Matthew,
Thats perfectly what i need, i am now able to delete 100 objects at one Go....Thanks a lot.
To Salvador,
when i ran the vbscript you pasted above i got an error message saying "Error deleting computername1", i think i need to specify what OU these computers belongs to because i got a big web of OU's in our AD..is that so?
BTW i do changed the file name to computers.txt and the domain information as well.
Thanks for helping me guys
Inderjit- Marked As Answer byIJSingh Thursday, July 02, 2009 11:55 AM
- Hi Inderjit
The reason the script failed is because the domain name and object path is hard coded:
set objComputer = GetObject("LDAP://CN=" & strComputer & ",CN=Computers,DC=fabrikam,DC=com")
This code is only an example of how you "might" modify it meet your requirements because your computer objects may not exists in the default computers container and your domain name probably isn't fabrikam.com!...besides who leaves their computer accounts in the computer container? The reality is you will move computer objects to an OU to apply group policy to them.
So here is a script i wrote which will read a text file from the scripts working directory. For each computer name read from the text file it will perform an ldap query to search for the computer objects adsPath value, bind to the object and delete it. It will log all the results including any error information to the scripts working directory. Here is the code...it may be overcomplicated but it has plenty of comments and error checking! Hope this helps
Cheers
Matt :)
'---------------------------------------------------------------------------------------------------------------------------- 'Script Name : DeleteComputerAccounts.vbs 'Author : Matthew Beattie 'Created : 02/07/09 'Description : This script reads a text file from the scripts working directory "computernames.txt". For each computername ' : it attempts to delete the computer account in Active Directory. '---------------------------------------------------------------------------------------------------------------------------- 'Initialization Section '---------------------------------------------------------------------------------------------------------------------------- Option Explicit Const ForReading = 1 Const ForWriting = 2 Const ForAppending = 8 Dim objFSO, wshShell, wshNetwork Dim scriptBaseName, scriptPath, scriptLogPath On Error Resume Next Set objFSO = CreateObject("Scripting.FileSystemObject") Set wshNetwork = Wscript.CreateObject("Wscript.Network") Set wshShell = CreateObject("Wscript.Shell") scriptBaseName = objFSO.GetBaseName(Wscript.ScriptFullName) scriptPath = objFSO.GetFile(Wscript.ScriptFullName).ParentFolder.Path scriptLogPath = scriptPath & "\" & scriptBaseName If Err.Number <> 0 Then Wscript.Quit End If On Error Goto 0 '---------------------------------------------------------------------------------------------------------------------------- 'Main Processing Section '---------------------------------------------------------------------------------------------------------------------------- On Error Resume Next PromptScriptStart ProcessScript If Err.Number <> 0 Then MsgBox "An Unexpected Error occurred!", vbCritical, scriptBaseName LogError "An Unexpected Error occurred!" End If PromptScriptEnd On Error Goto 0 Wscript.Quit '---------------------------------------------------------------------------------------------------------------------------- 'Name : ProcessScript -> Primary Function that controls all other script processing. 'Parameters : None -> 'Return : None -> '---------------------------------------------------------------------------------------------------------------------------- Function ProcessScript Dim domainName, ldapQuery, i, j Dim computerADsPaths, computerNames, computerName '------------------------------------------------------------------------------------------------------------------------- 'Get the distinguished Name of the domain to delete the computer accounts from. '------------------------------------------------------------------------------------------------------------------------- If Not GetDomainName("ldap", domainName) Then Exit Function End If '------------------------------------------------------------------------------------------------------------------------- 'Read the "computernames.txt" file in the script's working directory contain a list of computer accounts to delete. '------------------------------------------------------------------------------------------------------------------------- If objFSO.FileExists(scriptPath & "\computernames.txt") Then If Not GetScriptInput(computerNames, scriptPath & "\computernames.txt") Then Exit Function End If Else MsgBox DQ(scriptPath & "\computernames.txt") & " does not exist!", vbCritical, scriptBaseName Exit Function End If '------------------------------------------------------------------------------------------------------------------------- 'Delete the computer accounts in Active Directory '------------------------------------------------------------------------------------------------------------------------- For i = 0 To UBound(computerNames) Do '------------------------------------------------------------------------------------------------------------------- 'Perform an LDAP query to search for the distinguished Name of the computer. '------------------------------------------------------------------------------------------------------------------- ldapQuery = "Select distinguishedName From 'LDAP://" & _ domainName & "' Where objectCategory = 'computer' And sAMAccountName = '" & _ computerNames(i) & "$" & "'" If Not GetADObjectsADsPaths(computerADsPaths, ldapQuery) Then Exit Do End If '------------------------------------------------------------------------------------------------------------------- 'The LDAP query may have returned multiple results. Ensure only the correct computer account is deleted. '------------------------------------------------------------------------------------------------------------------- For j = 0 To UBound(computerADsPaths) On Error Resume Next computerName = Replace(Split(computerADsPaths(j), ",")(0), "LDAP://CN=", "") If Err.Number <> 0 Then LogError "Spliting String " & DQ(computerADsPaths(j)) Exit Do End If '------------------------------------------------------------------------------------------------------------- 'If the common name property of the computer object equals the computer name then delete the computer account. '------------------------------------------------------------------------------------------------------------- If StrComp(computerName, computerNames(i), vbTextCompare) = 0 Then If Not DeleteComputerAccount(computerADsPaths(j)) Then Exit Do End If LogMessage "Deleted computer account " & DQ(computerName) End If On Error Goto 0 Next Loop Until True Next End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : GetScriptInput -> Reads a text file to be used as the scripts input into a dictionary object. ' : -> Each line of the text file is added to a Dictionary object. Duplicate lines are ignored. 'Parameters : results -> Input/Output : An array of unique items read from the text file. ' : fileSpec -> String containing the folder path and file name of the script input file. 'Return : GetScriptInput -> Returns false if the user input file is invalid else returns true. '---------------------------------------------------------------------------------------------------------------------------- Function GetScriptInput(results, fileSpec) Dim objTextFile, objDict, line GetScriptInput = False Set objDict = NewDictionary On Error Resume Next Set objTextFile = objFSO.OpenTextFile(fileSpec, ForReading) If Err.Number <> 0 Then LogError "Opening Text File " & DQ(fileSpec) Exit Function End If Do Until objTextFile.AtEndOfStream line = objTextFile.Readline If Err.Number <> 0 Then LogError "Reading a line from within the file " & DQ(fileSpec) Exit Function End If If Not objDict.Exists(line) Then objDict(objDict.Count) = line End If Loop On Error Goto 0 GetScriptInput = True results = objDict.Items End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : GetDomainName -> Gets the name of the domain based on the input parameter parsed to the function. 'Parameters : format -> Defines the naming format the function returns. This can be: ' : -> "dns" : = microsoft.com ' : -> "ldap" : = DC=microsoft,DC=com ' : -> "netbios" : = MICROSOFT ' : result -> Input/outup : The name of the domain in the input specified format. 'Return : GetDomainName -> Returns True and the Domain Name in the input format specified otherwise returns False. '---------------------------------------------------------------------------------------------------------------------------- Function GetDomainName(format, result) Const AdsNameInitTypeGC = 3 Const AdsNameTypeNT4 = 3 Const AdsNameType1779 = 1 GetDomainName = False Dim domain, netbios Dim objTranslate On Error Resume Next Set objTranslate = CreateObject("NameTranslate") If Err.Number <> 0 Then Exit Function End If domain = GetObject("LDAP://RootDSE").Get("DefaultNamingContext") If Err.Number <> 0 Then LogError "Binding to RootDSE object" Exit Function End If On Error Goto 0 Select Case Lcase(format) Case "ldap" result = domain Case "dns" result = Mid(Replace(domain, ",DC=", "."), 4) Case "netbios" objTranslate.Init AdsNameInitTypeGC, "" objTranslate.Set AdsNameType1779, domain 'GetDomainName("ldap") netbios = Left(objTranslate.Get(AdsNameTypeNT4), Len(objTranslate.Get(AdsNameTypeNT4)) -1) If Err.Number <> 0 Then LogError "Translating NetBios Domain Name" Exit Function End If result = netbios End Select GetDomainName = True End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : GetADObjectsADsPaths -> Searches Active Directory for the objects specified in the LDAP query and ' : -> returns and Array of the object adsPaths. 'Parameters : adsPaths -> Output: An array. Each element of the array contains the ADsPath of an Object found. ' : ldapQuery -> String contain the LDAP query to process. 'Return : GetADObjectsADsPaths -> Returns True and an Array containing the ADsPaths of the objects returned from the ' : -> LDAP Query otherwise returns False. '---------------------------------------------------------------------------------------------------------------------------- Function GetADObjectsADsPaths(adsPaths, ldapQuery) Dim objectDict, objConnection, objCommand, objRecordSet, objectADsPath Const ADsScopeSubtree = 2 GetADObjectsADsPaths = False Set objectDict = NewDictionary Set objConnection = CreateObject("ADODB.Connection") Set objCommand = CreateObject("ADODB.Command") objConnection.Provider = "ADsDSOOBject" objConnection.Open "Active Directory Provider" objCommand.ActiveConnection = objConnection objCommand.Properties("Page Size") = 100 objCommand.Properties("Timeout") = 30 objCommand.Properties("Cache Results") = False objCommand.Properties("Searchscope") = ADsScopeSubtree objCommand.CommandText = ldapQuery On Error Resume Next Set objRecordSet = objCommand.Execute If objRecordSet.BOF And objRecordSet.EOF Then LogError "Executing ldap query " & DQ(ldapQuery) Exit Function End If objRecordSet.MoveFirst Do Until objRecordSet.EOF objectADsPath = "LDAP://" & Replace(objRecordSet.Fields("distinguishedName").Value, "/", "\/") objectDict(objectDict.Count) = objectADsPath objRecordSet.MoveNext Loop If Err.Number <> 0 Then LogError "Moving to the next record in the recordset" Exit Function End If objConnection.Close On Error Goto 0 adsPaths = objectDict.Items GetADObjectsADsPaths = True End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : DeleteComputerAccount -> Deletes a computer account object in Active Directory. 'Parameters : computerADsPath -> String containing the ADsPath of the computer object to delete. 'Return : DeleteComputerAccount -> Returns True if the computer object was successfully deleted otherwise returns False. '---------------------------------------------------------------------------------------------------------------------------- Function DeleteComputerAccount(computerADsPath) DeleteComputerAccount = False Dim objComputer On Error Resume Next Set objComputer = GetObject(computerADsPath) If Err.Number <> 0 Then LogError "Binding to computer account object " & DQ(computerADsPath) Exit Function End If objComputer.DeleteObject(0) If Err.Number <> 0 Then LogError "Deleting Computer object " & DQ(computerADsPath) Exit Function End If On Error Goto 0 DeleteComputerAccount = True End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : DQ -> Place double quotes around a string and replace double quotes ' : -> within the string with pairs of double quotes. 'Parameters : stringValue -> String value to be double quoted 'Return : DQ -> Double quoted string. '---------------------------------------------------------------------------------------------------------------------------- Function DQ (ByVal stringValue) If stringValue <> "" Then DQ = """" & Replace (stringValue, """", """""") & """" Else DQ = """""" End If End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : NewDictionary -> Creates a new dictionary object. 'Parameters : None -> 'Return : NewDictionary -> Returns a dictionary object. '---------------------------------------------------------------------------------------------------------------------------- Function NewDictionary Dim dict Set dict = CreateObject("scripting.Dictionary") dict.CompareMode = vbTextCompare Set NewDictionary = dict End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : GetScriptInput -> Reads a text file to be used as the scripts input into a dictionary object. ' : -> Each line of the text file is added to a Dictionary object. Duplicate lines are ignored. 'Parameters : results -> Input/Output : An array of unique items read from the text file. ' : fileSpec -> String containing the folder path and file name of the script input file. 'Return : GetScriptInput -> Returns false if the user input file is invalid else returns true. '---------------------------------------------------------------------------------------------------------------------------- Function GetScriptInput(results, fileSpec) Dim objTextFile, objDict, line GetScriptInput = False Set objDict = NewDictionary On Error Resume Next Set objTextFile = objFSO.OpenTextFile(fileSpec, ForReading) If Err.Number <> 0 Then LogError "Opening Text File " & DQ(fileSpec) Exit Function End If Do Until objTextFile.AtEndOfStream line = objTextFile.Readline If Err.Number <> 0 Then LogError "Reading a line from within the file " & DQ(fileSpec) Exit Function End If If Not objDict.Exists(line) Then objDict(objDict.Count) = line End If Loop On Error Goto 0 GetScriptInput = True results = objDict.Items End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : LogMessage -> Parses a message to the log file. 'Parameters: message -> String containnig the message to include in the log file. 'Return : None -> '---------------------------------------------------------------------------------------------------------------------------- Function LogMessage(message) If Not LogToFile(scriptLogPath & ".log", message) Then Exit Function End If End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : LogError -> Logs the current information about the error object. 'Parameters: message -> String containnig the message that relates to the process that caused the error. 'Return : None -> '---------------------------------------------------------------------------------------------------------------------------- Function LogError(message) Dim errorMessage errorMessage = "Error " & Err.Number & " (Hex " & Hex(Err.Number) & ") " & message & ". " & Err.Description If Not LogToFile(scriptLogPath & ".err", errorMessage) Then Exit Function End If End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : LogToFile -> Write a message into the user's network log file. 'Parameters : LogSpec -> String containing the Folder path, file name and extension of the log file to write to. ' : message -> String containing the Message to be logged. 'Return : LogToFile -> Returns True if successful otherwise returns false. '---------------------------------------------------------------------------------------------------------------------------- Function LogToFile(logSpec, message) LogToFile = False On Error Resume Next With objFSO.OpenTextFile(logSpec, ForAppending, True) .WriteLine Date & " " & Time & " " & message .Close End With If Err.Number <> 0 Then Exit Function End If On Error Goto 0 LogToFile = True End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : PromptScriptStart -> Prompt when script starts. 'Parameters : None 'Return : None '---------------------------------------------------------------------------------------------------------------------------- Function PromptScriptStart MsgBox "Now processing the " & DQ(Wscript.ScriptName) & " script.", vbInformation, scriptBaseName End Function '---------------------------------------------------------------------------------------------------------------------------- 'Name : PromptScriptEnd -> Prompt when script has completed. 'Parameters : None 'Return : None '---------------------------------------------------------------------------------------------------------------------------- Function PromptScriptEnd MsgBox "The " & DQ(Wscript.ScriptName) & " script has completed successfully.", vbInformation, scriptBaseName End Function '----------------------------------------------------------------------------------------------------------------------------- Proposed As Answer byMatthewBeattie Thursday, July 02, 2009 11:48 AM
- Edited byMatthewBeattie Thursday, July 02, 2009 11:53 AM
Matt,
Thank you very for spending time for me.
To be honest it’s a rocket science for me but I am sure if I get your assistance I will be able to design my own rocket and will be able to fly as well.
I will test the script and will let you know the results soon on this.
Thanks and Have a good day ahead...
Happy Learning!!!Cheers…
Inderjit- Hi Inderjit
No worries, happy to help. like i said...it's probably easier from the command prompt
dsquery computer -samid computerName1$ | dsrm -noprompt
another option would be to use Windows PowerShell with the quest command-lets for Active Directory.
http://www.quest.com/powershell/activeroles-server.aspx
Cheers
Matt :)

