Recently I had to develop a solution to automate renaming computers when refreshing the operating system on them using System Center Configuration Manager (SCCM) 2012 SP1. The rename needed to occur at the start of the refresh so most of the steps later in the task sequence occur with the system having the new name. The client knew what new name each machine should have. In this post I share the solution I came up with. This Zero-Touch Installation (ZTI) solution renames domain-joined computers, and the rename also occurs in Active Directory (AD).
A text file was created to indicate the new name for systems to be renamed (renameList.txt). Each line contains the old (existing) and the new name of a system, in that order, separated by a comma:
oldName,newName
This file is then placed on a share that is accessed by the target computer during deployment of the new OS.
To monitor the OS deployment and the rename operation on a large number of systems, the script creates a local log on the target system and centralized logs on a share. On a network share, three subfolders need to be created before hand: Success, Fail and NoRenameAttempt (the script allows you to use different names). A target computer will create a log named after its existing name (<existingName>.txt) in one of these folders. The log will contain information regarding the rename operation. When the rename succeeds, the log is created in the Success folder. When the rename fails, it is created in the Fail folder. When the rename operation is not attempted, the log is created in the NoRenameAttempt folder.
The rename operation is not attempted in these cases:
Description of Solution
A computer refresh during Operating System Deployment (OSD) starts when a Task Sequence (TS) is processed on a system's existing Operating System (OS). This solution renames the computer while the existing OS is running by executing the rename script in the "State Capture" group of the TS.A text file was created to indicate the new name for systems to be renamed (renameList.txt). Each line contains the old (existing) and the new name of a system, in that order, separated by a comma:
oldName,newName
This file is then placed on a share that is accessed by the target computer during deployment of the new OS.
To monitor the OS deployment and the rename operation on a large number of systems, the script creates a local log on the target system and centralized logs on a share. On a network share, three subfolders need to be created before hand: Success, Fail and NoRenameAttempt (the script allows you to use different names). A target computer will create a log named after its existing name (<existingName>.txt) in one of these folders. The log will contain information regarding the rename operation. When the rename succeeds, the log is created in the Success folder. When the rename fails, it is created in the Fail folder. When the rename operation is not attempted, the log is created in the NoRenameAttempt folder.
The rename operation is not attempted in these cases:
- The existing name is not found on the left of the comma in any of the lines of the file containing the old and new computer names.
- The new computer name is greater than 15 characters.
- The old name and the new name are the same in the file containing the old and new computer names.
A domain user account is used to rename the computer. This account must have the rights to rename computer objects in AD and perform a domain join operation, to read the rename list file on a network share, and to create and write the log files on the configured network share. Check this article about delegating domain join control to a user account.
Implementing Solution
To implement the solution, configure the rename list, the log locations, and the domain join account at the beginning of the VB script (in red). Next, place the script in an SCCM package and distribute it to the appropriate distribution point(s). Then, add a "Run Command Line" step in your task sequence where you want the rename to occur. This step will execute the VB script. Below are the details of the TS step.
In the task sequence step details, you can see that I put the script in a file called renamePC-v3.vbs, I put the file in a package called renamePC-v3, and I indicated that the domain join user account is used to run the step (replace <domainName> with your domain name, and <domainAccount> with your domain join user account).
Script
(In the event that the copy and paste operation breaks the lines of the script, you can also download it from the Microsoft Gallery).
' February 2013
' by Romano Jerez
'
' OK to use and distribute if author information is kept
' ===========================================================
Option Explicit
Dim strPCList, objFSO, objWshNet, strLocalPC, objPCFile, strCurrentLine
Dim arrayName, strOldName, strNewName, intExitCode, objComputer
Dim objWMIService, Return, bFound, strLocalLogFile, objLocalLogFile
Dim strUserAccount, strUserPassword, strRemoteLogFileSuccess
Dim strRemoteLogFileFail, strRemoteLogFileNoRename, objRemoteLogFileSuccess
Dim objRemoteLogFileFail, objRemoteLogFileNoRename, bSameName
Dim strRemoteLogFileSuccessShare, strRemoteLogFileFailShare
Dim strRemoteLogFileNoRenameShare
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
' *** Configure file with computer list ***
strPCList = "\\<serverName>\<shareName>\renameList.txt"
' *****************************************
' *** Configure local log File and remote log locations ***
'
strLocalLogFile = "c:\windows\temp\pcRename.log"
strRemoteLogFileSuccessShare = "\\<serverName>\<shareName>\Success"
strRemoteLogFileFailShare = "\\<serverName>\<shareName>\Fail"
strRemoteLogFileNoRenameShare = "\\<serverName>\<shareName>\NoRenameAttempt"
'
' ********************************
' *** Configure Account with permissions to rename computer in AD ***
'
strUserAccount = "<domainName>\<domainAccount>"
strUserPassword = "<password>"
'
' ********************************
Set objWshNet = CreateObject("WScript.Network")
Set objFSO = CreateObject("Scripting.FileSystemObject")
strLocalPC = objWshNet.ComputerName
strRemoteLogFileSuccess = strRemoteLogFileSuccessShare & "\" & strLocalPC & ".txt"
strRemoteLogFileFail = strRemoteLogFileFailShare & "\" & strLocalPC & ".txt"
strRemoteLogFileNoRename = strRemoteLogFileNoRenameShare & "\" & strLocalPC & ".txt"
initializeLogging
Set objPCFile = objFSO.OpenTextFile(strPCList, ForReading)
intExitCode = 99
bSameName = vbFalse
bFound = vbFalse
Do Until (objPCFile.AtEndOfStream)
strCurrentLine = objPCFile.Readline
If Len(strCurrentLine) > 0 Then
arrayName = Split(strCurrentLine, ",", -1, 1)
strOldName = Trim(arrayName(0))
strNewName = Trim(arrayName(1))
If strLocalPC = strOldName Then
bFound = vbTrue
If (Len(strNewName)) > 15 Then
WScript.Echo "Not renaming as new name has more than 15 characters: " & strNewName
writeToLog("Not renaming as new name has more than 15 characters: " & strNewName)
LogNoRename("Not renaming as new name has more than 15 characters: " & strNewName)
ElseIf strOldName = strNewName Then
bSameName = vbTrue
WScript.Echo "Not renaming as old and New name are the same for " & strLocalPC
writeToLog("Not renaming as old and New name are the same for " & strLocalPC)
LogNoRename("Not renaming as old and New name are the same for " & strLocalPC)
Else
WScript.Echo "Old name: " & strOldName & ". Changing to " & strNewName
writeToLog("Old name: " & strOldName & ". Changing to " & strNewName)
intExitCode = Rename(strNewName)
End If
End If
End If
Loop
If Not bFound Then
WScript.Echo strLocalPC & " not found in list as old computer. No renaming attempted."
writeToLog(strLocalPC & " not found in list as old computer. No renaming attempted.")
LogNoRename(strLocalPC & " not found in list as old computer. No renaming attempted.")
End If
If intExitCode = 99 Then ' didn't run Rename function
intExitCode = 0 ' but return that the script ran successfully
End If
cleanUp
WScript.Quit(intExitCode)
' *********************************************************************
Sub cleanUp
WScript.Echo "Exit code: " & intExitCode
writeToLoG("Exit code: " & intExitCode)
objPCFile.Close
objLocalLogFile.Close
End Sub
' *****************
Sub initializeLogging
If objFSO.FileExists(strLocalLogFile) Then
Set objLocalLogFile = objFSO.OpenTextFile(strLocalLogFile, ForAppending)
Else
Set objLocalLogFile = objFSO.CreateTextFile(strLocalLogFile)
objLocalLogFile.Close
Set objLocalLogFile = objFSO.OpenTextFile(strLocalLogFile, ForWriting)
End If
objLocalLogFile.WriteLine(Now())
End Sub
' *****************
Sub LogNoRename(strMessage)
If objFSO.FileExists(strRemoteLogFileNoRename) Then
Set objRemoteLogFileNoRename = objFSO.OpenTextFile(strRemoteLogFileNoRename, ForAppending)
Else
Set objRemoteLogFileNoRename = objFSO.CreateTextFile(strRemoteLogFileNoRename)
objRemoteLogFileNoRename.Close
Set objRemoteLogFileNoRename = objFSO.OpenTextFile(strRemoteLogFileNoRename, ForWriting)
End If
objRemoteLogFileNoRename.WriteLine(Now())
objRemoteLogFileNoRename.WriteLine(strMessage)
objRemoteLogFileNoRename.Close
End Sub
' ******************
Sub LogRenameFailed(strMessage)
If objFSO.FileExists(strRemoteLogFileFail) Then
WScript.Echo "File exists"
Set objRemoteLogFileFail = objFSO.OpenTextFile(strRemoteLogFileFail, ForAppending)
Else
Set objRemoteLogFileFail = objFSO.CreateTextFile(strRemoteLogFileFail)
objRemoteLogFileFail.Close
Set objRemoteLogFileFail = objFSO.OpenTextFile(strRemoteLogFileFail, ForWriting)
End If
objRemoteLogFileFail.WriteLine(Now())
objRemoteLogFileFail.WriteLine(strMessage)
objRemoteLogFileFail.Close
End Sub
' ******************
Sub LogRenameSucceded(strMessage)
If objFSO.FileExists(strRemoteLogFileSuccess) Then
Set objRemoteLogFileSuccess = objFSO.OpenTextFile(strRemoteLogFileSuccess, ForAppending)
Else
Set objRemoteLogFileSuccess = objFSO.CreateTextFile(strRemoteLogFileSuccess)
objRemoteLogFileSuccess.Close
Set objRemoteLogFileSuccess = objFSO.OpenTextFile(strRemoteLogFileSuccess, ForWriting)
End If
objRemoteLogFileSuccess.WriteLine(Now())
objRemoteLogFileSuccess.WriteLine(strMessage)
objRemoteLogFileSuccess.Close
End Sub
' ****************************************
Function Rename(strName)
Set objWMIService = GetObject("Winmgmts:root\cimv2")
For Each objComputer in objWMIService.InstancesOf("Win32_ComputerSystem")
Return = objComputer.Rename(strName,strUserPassword,strUserAccount)
If Return <> 0 Then
WScript.Echo "Rename to " & strName & " failed. Error = " & Err.Number
writeToLog("Rename to " & strName & " failed. Error = " & Err.Number)
LogRenameFailed("Rename to " & strName & " failed. Error = " & Err.Number & vbCrLf & "Exit code: " & Return)
Else
WScript.Echo "Rename to " & strName & " succeeded. Restart is needed."
writeToLog("Rename to " & strName & " succeeded. Restart is needed.")
LogRenameSucceded("Rename to " & strName & " succeeded. Restart is needed.")
End If
Next
Rename = Return
End Function
' ***************************************
Sub writeToLog(strMessage)
objLocalLogFile.WriteLine(strMessage)
End Sub
' ***************************************