AD Migration : Cleanup extensionAttributes

AD Migration : Cleanup extensionAttributes

The Quest migration tools use extensionAttributes to keep objects in the source and destination domains. the script below will remove these entries. Change the desired extensionAttributes you wish to purge, as highlighted in red. You can also change the scope by changing strFilter and strOU.

   Const ADS_PROPERTY_DELETE = 4
   Const ADS_PROPERTY_UPDATE = 2
   Const ADS_PROPERTY_CLEAR = 1
  
   Dim strFilter ‘As String
   Dim oConnection ‘As ADODB.Connection
   Dim oRecordSet ‘As ADODB.RecordSet
   Dim strQuery ‘As String
   Dim strDomainNC ‘As String
   Dim oRootDSE ‘As IADs
   Dim vArray ‘As Variant()
   Dim vSid ‘As Variant
   Dim oDirObject ‘As Variant
   Dim strOU ‘As String

   ‘ Find the domain naming context
   set oRootDSE = GetObject(“LDAP://RootDSE”)
   strDomainNC = oRootDSE.Get(“defaultNamingContext”)
   set oRootDSE = Nothing

   ‘ Setup the ADO connection
   Set oConnection = CreateObject(“ADODB.Connection”)
   oConnection.Provider = “ADsDSOObject”
   oConnection.Open “ADs Provider”
   strOU = “OU=IT,”
   strFilter = “(&(objectClass=user)(objectCategory=person))”
   ‘strFilter = “(&(objectClass=computer))”
   ‘strFilter = “(&(objectClass=group))”
   strFilter = “(&(objectClass=contact))”
   strQuery = “;” & strFilter & “;distinguishedName,objectClass,name,extensionAttribute8,extensionAttribute9,targetAddress”

   ‘Execute the query
   set oRecordSet = oConnection.Execute(strQuery)

   if oRecordSet.Eof then
     WScript.Echo “No objects were found”
     WScript.Quit(0)
   Else
     Dim vClasses ‘As Variant
     Dim strClass ‘As String

     WScript.Echo “The following objects were found:”

     ‘ Iterate through the objects that match the filter
     While Not oRecordset.Eof
        vClasses = oRecordset.Fields(“objectClass”).Value
        strClass = vClasses(UBound(vClasses))
        If IsNull(oRecordSet.Fields(“extensionAttribute8“).Value ) and IsNull(oRecordSet.Fields(“extensionAttribute9“).Value) Then
            ‘Values Empty
        Else
            WScript.Echo chr(34) & oRecordset.Fields(“distinguishedName”).Value  & chr(34) & “,” & _
              chr(34) & oRecordset.Fields(“name”).Value   & chr(34) & “,” & _
              chr(34) & oRecordset.Fields(“extensionAttribute8“).Value & chr(34) & “,” & _
              chr(34) & oRecordset.Fields(“extensionAttribute9“).Value & chr(34)

              If InStr(oRecordset.Fields(“name”).Value, “/”) Then
                  ‘Ignore entries with a “/” in the canonical name – this will cause the script to fail
              Else
                set oDirObject = GetObject(“LDAP://” & oRecordset.Fields(“distinguishedName”).Value)
                oDirObject.PutEx ADS_PROPERTY_CLEAR, “extensionAttribute8“,  0
                oDirObject.SetInfo   
                oDirObject.PutEx ADS_PROPERTY_CLEAR, “extensionAttribute9“,  0
                  oDirObject.SetInfo
                End If   
        End if
        oRecordset.MoveNext
     Wend
   End if

   ‘Clean up
   Set oRecordset = Nothing
   Set oConnection = Nothing

 
Function OctetToHexStr(sOctet)
  Dim k
  OctetToHexStr = “”
  For k = 1 To Lenb(sOctet)
    OctetToHexStr = OctetToHexStr _
      & Right(“0” & Hex(Ascb(Midb(sOctet, k, 1))), 2)
  Next
End Function

AD Migration : Dump SIDHistory

AD Migration : Dump SIDHistory

Use the following script to dump SIDHistory for all objcts, or those under a particular OU. Change the strOU attrobute to “” if you wish to dump the SIDHistory for ALL objects, limit the objects that the SIDHistory  is gathered for by using the strFilter attribute. For example:

  • To report on User Account only, change strFilter to: “(&(objectClass=user)(objectCategory=person))”
  • To report on Groups chang strFilter to “(objectClass=Group)”

Save the script below into a vbs file then execute using the command: cscript.exe /nologo .vbs >> SIDHistory

Const ADS_PROPERTY_DELETE = 4

   Const ADS_PROPERTY_UPDATE = 2

   Dim strFilter ‘As String
   Dim oConnection ‘As ADODB.Connection
   Dim oRecordSet ‘As ADODB.RecordSet
   Dim strQuery ‘As String
   Dim strDomainNC ‘As String
   Dim oRootDSE ‘As IADs
   Dim vArray ‘As Variant()
   Dim vSid ‘As Variant
   Dim oDirObject ‘As Variant
   Dim strOU ‘As String

   ‘ Find the domain naming context
   set oRootDSE = GetObject(“LDAP://RootDSE”)
   strDomainNC = oRootDSE.Get(“defaultNamingContext”)
   set oRootDSE = Nothing

   ‘ Setup the ADO connection
   Set oConnection = CreateObject(“ADODB.Connection”)
   oConnection.Provider = “ADsDSOObject”
   oConnection.Open “ADs Provider”
   strOU = “OU=IT,”
   strFilter = “(&(objectClass=*))”
   strQuery = “;” & strFilter & “;distinguishedName,objectClass,name,sidHistory;subtree”

   ‘Execute the query
   set oRecordSet = oConnection.Execute(strQuery)

   if oRecordSet.Eof then
     WScript.Echo “No objects were found”
     WScript.Quit(0)
   Else
     Dim vClasses ‘As Variant
     Dim strClass ‘As String
     WScript.Echo “Name, Class, DN, SIDHistory”
     While Not oRecordset.Eof
        vClasses = oRecordset.Fields(“objectClass”).Value
        strClass = vClasses(UBound(vClasses))
        If IsNull(oRecordSet.Fields(“sIDHistory”).Value ) Then
           ‘object does not have a sidHistory
        Else
            ‘WScript.Echo chr(34) & oRecordset.Fields(“name”).Value & chr(34) & “,” & _
            ‘    chr(34) & strClass & chr(34) & “,” & chr(34) & _
            ‘    oRecordset.Fields(“distinguishedName”).Value & chr(34)
           
            set oDirObject = GetObject(“LDAP://” & oRecordset.Fields(“distinguishedName”).Value)
               vArray = oDirObject.GetEx(“sIDHistory”)
              
               For Each vSid in vArray
                   If OctetToHexStr(vSid) > “” Then
                       WScript.Echo chr(34) & oRecordset.Fields(“name”).Value & chr(34) & “,” & _
                        chr(34) & strClass & chr(34) & “,” & chr(34) & _
                        oRecordset.Fields(“distinguishedName”).Value & chr(34) & “,” & chr(34) & _
                        OctetToHexStr(vSid)    & chr(34)
                End If
            Next
        End if

        oRecordset.MoveNext
     Wend
   End if

   ‘Clean up
   Set oRecordset = Nothing
   Set oConnection = Nothing

 
Function OctetToHexStr(sOctet)
  Dim k
  OctetToHexStr = “”
  For k = 1 To Lenb(sOctet)
    OctetToHexStr = OctetToHexStr _
      & Right(“0” & Hex(Ascb(Midb(sOctet, k, 1))), 2)
  Next
End Function

Windows 2008 : DCPromo Administrator Account Error

Windows 2008 : DCPromo Administrator Account Error

When trying to promote a Windows Server 2006 x84 R2 server to a domain controller of a new forest I obtained the following error which stopped the promotion of the system:

The local Administrator account becomes the domain Administrator account when you create a new domain. The new domain cannot be created because the local Administrator account password does not meet requirements.

Currently, a password is not required for the local Administrator account. We recommend that you use the net user command-line tool with the /passwordreg:yes option to require a password for this account before you create the new domain; otherwise, a password will not be required for the domain Administrator account.

To resolve this error, open a command-prompt as Administrator and execute the following command: net user Administrator /passwordreq:yes *

This will ensure that the Administrator account requires a password, and that a password is set. After running this I was able to proceed with the promotion of the server to a DOmain Controller.

 

Migration : SIDHistory Cleanup vbScript

Migration : Cleanup SIDHistory

One of the last steps in an Actiove Directory migration is the removal of SIDHistory from migrated users, computers and groups. This will help reduce the size of the directory database.

Before cleanup of SIDHistory domain-wide, you should perform cleanup on a single OU and analyse the effects on applications such as AzMan and Sharepoint. Watch out for DCOM remote launch pernmissions. It is possible to modify the script to target individual users for this purpose.

The following VBScript will perform a SIDHistory cleanup of all user objects (this can be altered) within a particular OU. It is possible to change the LDAP filter and OU string to suit testing and cleanup of various object classes. Alternately, by changing the line strOU = “OU=UK,” to strOU = “” willl perform SIDHistory cleanupon all objects within every OU.

Remember to perform cleanup on the following objectClass types, changing the code in RED will allow you to perform cleanup of different objectClass’: User, Computer, Contact, Group.

   Const ADS_PROPERTY_DELETE = 4
   Const ADS_PROPERTY_UPDATE = 2

   Dim strFilter ‘As String
   Dim oConnection ‘As ADODB.Connection
   Dim oRecordSet ‘As ADODB.RecordSet
   Dim strQuery ‘As String
   Dim strDomainNC ‘As String
   Dim oRootDSE ‘As IADs
   Dim vArray ‘As Variant()
   Dim vSid ‘As Variant
   Dim oDirObject ‘As Variant
   Dim strOU ‘As String

   ‘ Find the domain naming context
   set oRootDSE = GetObject(“LDAP://RootDSE”)
   strDomainNC = oRootDSE.Get(“defaultNamingContext”)
   set oRootDSE = Nothing

   ‘ Setup the ADO connection
   Set oConnection = CreateObject(“ADODB.Connection”)
   oConnection.Provider = “ADsDSOObject”
   oConnection.Open “ADs Provider”
   
   ‘Target OrganizationalUnit
   strOU = “OU=UK,”
   
   ‘Target objectClass
   strFilter = “(&(objectClass=user))”
   strQuery = “;” & strFilter & “;distinguishedName,objectClass,name,sidHistory;subtree”

   ‘Execute the query
   set oRecordSet = oConnection.Execute(strQuery)

   if oRecordSet.Eof then
     WScript.Echo “No objects were found”
     WScript.Quit(0)
   Else
     Dim vClasses ‘As Variant
     Dim strClass ‘As String

     WScript.Echo “Name, Class, DN, SIDHistory”

     ‘ Iterate through the objects that match the filter
     While Not oRecordset.Eof
        vClasses = oRecordset.Fields(“objectClass”).Value
        strClass = vClasses(UBound(vClasses))
       
        If IsNull(oRecordSet.Fields(“sIDHistory”).Value ) Then
           WScript.Echo “This object does not have a sidHistory”
        Else
            set oDirObject = GetObject(“LDAP://” & oRecordset.Fields(“distinguishedName”).Value)
               vArray = oDirObject.GetEx(“sIDHistory”)
              
             For Each vSid in vArray
                   If OctetToHexStr(vSid) > “” Then
                       WScript.Echo chr(34) & oRecordset.Fields(“name”).Value & chr(34) & “,” & _
                        chr(34) & strClass & chr(34) & “,” & chr(34) & _
                        oRecordset.Fields(“distinguishedName”).Value & chr(34) & “,” & chr(34) & _
                        OctetToHexStr(vSid)    & chr(34)
                End If
            Next

            oDirObject.SetInfo
            WScript.Echo “The sidHistory has been cleared for this object!”
        End if
        WScript.Echo
        oRecordset.MoveNext
     Wend
   End if

   ‘Clean up
   Set oRecordset = Nothing
   Set oConnection = Nothing

Function OctetToHexStr(sOctet)
  Dim k
  OctetToHexStr = “”
  For k = 1 To Lenb(sOctet)
    OctetToHexStr = OctetToHexStr _
      & Right(“0” & Hex(Ascb(Midb(sOctet, k, 1))), 2)
  Next
End Function

Migration ; Outlook 2007 Client Temporary Mailbox

Autodiscover Outlook 2007 Client Issues

During the migration of mailboxes from a Windows 2000 Forest / Exchange 2000 Org we had an issue where migrated users with non-migrated mailboxes were recieving the following error on loading their Outlook 2007 client:

 “Your mailbox has been temporarily moved on Microsoft Exchange Server. A temporary mailbox exists, but might not have all of your data. You can connect to the temporary mailbox or work offline with all of your old data. If you choose to work with your old data, you cannot send or receive e-mail messages.”

For some reaosn the client had detected the users stub-mailbox in the target environment and automatically configured the users MAPI profile to connect to it. The main issue with this being that this mailbox was incable of recieving email due to the redirect setup back to the source environment. Thus, the only way to resolve this for the user was to rebuild their MAPI profile, until they load Outlook agin and the same thing happens!

First lets look at why this was happenin:

  • Exchange 2007 was running in the target domain.
  • The users were logging in to the target domain, accessing a mailbox in the source using the Associated External Account (AEA)setting on the source mailbox.
  • Affected clients were running Outlook 2007
  • There were a small number of migrated mailbox users connecting to the new Exchange Org.

Outlook 2007 supports Autodsover, which was available for the users that were loggin in to the target domain. Using OWA and locating a user in the GAL or a Free/Busy lookup in the Outlook ‘thick’ client would trigger the stub-mailbox to become ‘active’ – it would suddenly have itemCount and totalItemSize attributes. On load Outlook 2007 performs autodiscovery, it would then detect the users new mailbox and display the above message.

The biggest problem here is that nothing is actually going wrong. Exchange is designed to create a mailbox on Free/Busy lookup via OWA or the full Outlook client. So the question was how to break Autodiscover for non-migrated users only.

Initially I configured the AutodiscoverServiceInternalUri to an invalid URL and the problem affecting non-migrated users went away. With this came a wealth of further issues affecting migrated users:

  • The Offline Address Book failed to download for Cached Exchange Mode users.
  • The scheduling features would fail to work with ‘Item could not be found’ error
  • The Out of Office Assistant would fail to load.

All of these side-effects were caused by Autodiscover being unavailable to Outlook 2007 clients connecting to the new Exchange 2007 Org.

Next we configured the IIS Virtual Directory on the Client Access Servers to Deny Connection to users that had not been migrated. This meant compiling and maintaining a Active Directory Security Group containing all mailbox migrated users. Whilst this stopped the clients detecting the mailbox on the new server it meant that non-migrated users were plagued with Authentication requests to connect to the Client Access Servers asthe Outlook Clients had still detected the Autodiscover Configuration via the SCP record in the Active Directory.

This then led to the final, and successful, solution. Using the group containing all migrated mailbox users we configured the SCP record on each CA server in the Active Directory, via ADSIedit, so that ‘Authenticated Users’ has no defined read permissions and the new security group containing all migrated usershad defined read permissions. This meant that clients running under a non-migrated user account could not find the autodiscover settings using the SCP record as they were unable to read this in the Active Directory. The images below detail this process:

Autodicover SCP Record in ADSIedit

The Default Permissions were configured as follows:

Autodisocver Default Permissions  Autodiscover Default Permissions

The newly configured permissoins for Authenticated Users during the migration:

Autodiscover New Permisisons

And the newly configured permissions for the group containing all migrated mailbox users:

 Autodiscover New Permissions

Migration ; Stage Two – Active Directory Cleanup

Why migrate unused service accounts, user objects and computer accounts from your source domains to the target? A migration is an ideal opportunity to cleanup all of the disused and legacy objects from your environment.

A simple way to achieve a user purge to is to query the lastLogonTimeStamp attribute on all user objects. This will immediately provide a reliable picture of recent account utilisation across the domain. The lastLogonTimeStamp attribute is new to Windows Server 2003, as opposed to the Windows 2000 lastLogon attribute which will vary on each Domain Controller within the domain, is replicated to all Domain Controllers.

The following vbScript will perform the query, creating a report on recent account usage:

Sub ListUsers( strDomain )
Set objComputer = GetObject(“WinNT://” & strNetBIOSDomain )
objComputer.Filter = Array( “User” )
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set objFile = fso.CreateTextFile(fileUserLst, True)
Dim strUserName, objUser, objLogon, intLogonTime

‘ Constants for the NameTranslate object.
Const ADS_NAME_INITTYPE_GC = 3
Const ADS_NAME_TYPE_NT4 = 3
Const ADS_NAME_TYPE_1779 = 1

For Each objUser In objComputer
On Error Resume Next

‘ Specify the NT name of the user.
strNTName = objUser.Name

‘ Use the NameTranslate object to convert the NT user name to the
‘ Distinguished Name required for the LDAP provider.
Set objTrans = CreateObject(“NameTranslate”)

‘ Initialize NameTranslate by locating the Global Catalog.
objTrans.Init ADS_NAME_INITTYPE_GC, “”
‘ Use the Set method to specify the NT format of the object name.
objTrans.Set ADS_NAME_TYPE_NT4, strNetBIOSDomain & “” & strNTName

‘ Use the Get method to retrieve the RPC 1779 Distinguished Name.
strUserDN = objTrans.Get(ADS_NAME_TYPE_1779)

‘ Bind to the user object in Active Directory with the LDAP provider.
Set objUser = GetObject(“LDAP://” & strUserDN)

‘MsgBox(“DN = ” & strUserDN)
‘ This code prints the last logon timestamp for a user.
set objLogon = objUser.Get(“lastLogonTimestamp”)
intLogonTime = objLogon.HighPart * (2^32) + objLogon.LowPart
intLogonTime = intLogonTime / (60 * 10000000)
intLogonTime = intLogonTime / 1440

‘…and writes to file specified by user
objFile.WriteLine( objUser.Name & “;” & intLogonTime + #1/1/1601#)

Next
End Sub
‘****************************************************************************
‘ Main
‘ ****************************************************************************
Do
  strNetBIOSDomain = inputbox(“Please enter the NetBios domainname. example; mydomain”, “NetBIOS domain name” )
  fileUserLst = inputbox(“Please enter a file name and path for the output file.”, “File path”, “C:” & strNetBIOSDomain & ” users.csv”)
Loop until strNetBIOSDomain “”

ListUsers( strDomain )

With regards to computer accounts, don’t worry too much about the cleanup of these objects as you will be migrating all of the active computer objects within your environment individually duringthe migration process. Therefore what is left is likely to be the disused / legacy objects.

I would also suggest reviewing security group memberships and useage. This can be achieved by looking at logon scripts for any group based functions, group policy assignment and file share permission auditing. DSQUESRY can be used to return these values for each group individually:

dsquery * “” -attr name createTimestamp modifyTimestamp

Or for all security groups (well all objects in the case of this command) in an OU:

dsquery * “OU=Security Groups,DC=Domain,DC=local” -attr name modifyTimeStamp

This helps to further justify normalising your OU structure prior to the migration process (see here.) Without normalisation of the Security Gorups into a particlar OU it would be more complex to return the required information.

Perform the same steps with your Distribution Lists to ensure you’re not wasting time an effort migrating objects which are no longer in use.

Finally, if you are using the Quest tools identify which customAttributes are in use within your environment.These attributes are essential during the migration and each source pair will require 2 free sttributes for the duration of the migration.

 

Migration ; Stage One – Active Directory Normlisation

One of the first steps towards simplifying your Active Directory migration is directory normalisation. This process involves re-designing each of your Organisational Unit structures in order that they are identicle in each source domain. This allows you to locate service accounts, generic accounts and resource mailboxes in seperate OUs, thus allowing identification of these resources in advance of the migration. Numbers are important during a migration, so when this process is finished you’ll be able to identify:

1) Number of non-adminisitrative user and computer accounts in each source domain
2) Number of service accounts in the domain
3) Number of generic logon accounts in the domain
4) Number of resource mailboxes in the domain

 An example of a normalised OU strufture is as follows:

 

You can clearly see the division of user and computer objects, Exchange objects (excluding User Mailboxes), service accounts and server objects. This structure allows for simple Group Policy management as well as simplified administration.

By performing the above process on each of your source environments this will speed up the process of migration as the administrators do not necessariliy need to be familiar with the source environments to perform a stream-lined and well-structured migration. Just be careful when moving objects into new OUs as this can change Group Policy inheritance!

 

VBScript; List Exchange Mailbox DACL / ACE / ACL

The below VBScript will return all user mailboxes on your environment and display the DACL for the mailbox. This helps to easily identify custom ACEs during an Exchange migration enabling you to pre-configure permissions in your target environment. The script is useful in identifying groups of users that work together and thus need access to each others mailboxes.

The script will create an Excel file, although I have stopped the script form closing the Excel file as this will cause issues in the event of you running Office versons earlier than 2003.

 

On Error Resume Next

sXLS = “C:\mbx-access-rights-export.xls”   ‘excel file must be created before script is ran

 Set objRootDSE = GetObject(“LDAP://rootDSE”)
 strDNSDomain = objRootDSE.Get(“defaultNamingContext”)

 ‘Start the ADO connection
 Set objCommand = CreateObject(“ADODB.Command”)
 Set objConnection = CreateObject(“ADODB.Connection”)
 objConnection.Provider = “ADsDSOObject”
 objConnection.Open “Active Directory Provider”
 objCommand.ActiveConnection = objConnection

 ‘Set the ADO connection query strings
 StartNode = strDNSDomain
 SearchScope = “subtree”

 FilterString = “(&(objectCategory=person)(objectClass=user)” _
             & “(description=*)” _
              & “(mail=*))” _
                 ‘& “(!(userAccountControl:1.2.840.113556.1.4.803:=2)))”
 Attributes = “adspath”

 ‘Create the LDAP-Query
 LDAPQuery = “;” & FilterString & “;” _
                & Attributes & “;” & SearchScope

 objCommand.CommandText = LDAPQuery
 objCommand.Properties(“Page Size”) = 100
 objCommand.Properties(“Timeout”) = 30
 objCommand.Properties(“Cache Results”) = False

 Set objRecordSet = objCommand.Execute

 Set objExcel = CreateObject(“Excel.Application”)
    objExcel.Application.DisplayAlerts = False
    objExcel.Visible = True

     ‘Set objWorkbook = objExcel.Workbooks.Open(sXLS)
        objExcel.Workbooks.Add

        objExcel.Cells(1,1).Value = “Logon Name”
        objExcel.Cells(1,2).Value = “Display Name”
        objExcel.Cells(1,3).Value = “Email Address”
        objExcel.Cells(1,4).Value = “Mailbox Rights”

          xRow = 1
          yColumn = 1

       Do Until yColumn = 5
               objExcel.Cells(xRow,yColumn).Font.Bold = True
            objExcel.Cells(xRow,yColumn).Font.Size = 11
            objExcel.Cells(xRow,yColumn).Interior.ColorIndex = 11
            objExcel.Cells(xRow,yColumn).Interior.Pattern = 1
            objExcel.Cells(xRow,yColumn).Font.ColorIndex = 2
            objExcel.Cells(xRow,yColumn).Borders.LineStyle = 1
            objExcel.Cells(xRow,yColumn).WrapText = True
    yColumn = yColumn + 1
          Loop

    x = 2
    y = 1

     If NOT objRecordSet.eof Then
        objRecordSet.MoveFirst
          While Not objRecordset.EOF
            Set objUser = GetObject(objRecordSet.Fields(“AdsPath”).Value)
            y1 = y
                      objExcel.Cells(x,y1).Value = objUser.sAMAccountName
                      y1 = y1 + 1
                      objExcel.Cells(x,y1).Value = objUser.displayName
                y1 = y1 + 1
                      objExcel.Cells(x,y1).Value = objUser.mail
                y1 = y1 + 1
                    Set oSecurityDescriptor = objuser.Get(“msExchMailboxSecurityDescriptor”)
                    Set dacl = oSecurityDescriptor.DiscretionaryAcl
                    Set ace = CreateObject(“AccessControlEntry”)
                      For Each ace In dacl
                        mystring = ace.Trustee
                        If (ace.AceType = ADS_ACETYPE_ACCESS_ALLOWED) Then
                            x = x + 1
                                  objExcel.Cells(x,y1).Value = mystring & ” has access”
                        ElseIf (ace.AceType = ADS_ACETYPE_ACCESS_DENIED) Then
                            x = x + 1
                                  objExcel.Cells(x,y1).Value = mystring & ” is denied access”
                        End If
                      Next
                      x = x + 1 ‘go to the next Row
              objRecordSet.MoveNext
          Wend
     End If

 objExcel.Columns(“A:D”).Select
 objExcel.Selection.HorizontalAlignment = 3     ‘center all data
 objExcel.Selection.Borders.LineStyle = 1     ‘apply borders
 objExcel.Columns(“A:AH”).EntireColumn.AutoFit  ‘autofit all columns

 appVerInt = split(objExcel.Version, “.”)(0)
    If appVerInt-Excel2007 >=0 Then
          objExcel.ActiveWorkbook.SaveAs(sXLS), 56  ‘office 2007
    Else
          objExcel.ActiveWorkbook.SaveAs(sXLS), 43  ‘office 2003
    End If

 ‘objExcel.Quit

 set objExcel = Nothing
 Set objUser = Nothing

msgbox “Done!”
WScript.Quit

VBSCript : Force Automatic DNS config on DHCP enabled NIC

Useful for AD / DNS migrations, this script will scan a text file containing a list of PC names and will interrogate each one to see if it is DHCP enabled on each NIC. If DHCP is enabled it will delete any manually assigned DNS servers and configure the NIC to automatically get the DNS servers via DHCP.

‘ Script to scan PCs for network cards that use DHCP and remove
‘ all manually set DNS servers for those cards only

On Error Resume Next

Const ForReading = 1

Set objFSO = CreateObject(“Scripting.FileSystemObject”)
Set objTextFile = objFSO.OpenTextFile _
    (“hosts.txt”, ForReading)

Do Until objTextFile.AtEndOfStream
    strComputer = objTextFile.Readline
    Wscript.Echo “Processing ” & strComputer
Set objWMIService = GetObject(“winmgmts:” _
  & “{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2”)
Set colNicConfigs = objWMIService.ExecQuery _
  (“SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True”)
 
For Each objNicConfig In colNicConfigs
    WScript.Echo VbCrLf & ”  Network Adapter ” & objNicConfig.Index & _
      VbCrLf & ”    ” & objNicConfig.Description & VbCrLf
    If objNicConfig.DHCPEnabled Then
                intSetDNSServers = _
                objNicConfig.SetDNSServerSearchOrder
    Else
        WScript.Echo “DHCP not enabled on this card”
    End If
Next
Loop