Quantcast
Channel: NETvNext Blog
Viewing all articles
Browse latest Browse all 63

Rename PCs During SCCM OSD ZTI

$
0
0
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).

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:

  1. 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.
  2. The new computer name is greater than 15 characters.
  3. 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

' ***************************************


Viewing all articles
Browse latest Browse all 63

Trending Articles