Need to bulk modify all TS Profile/RDS Profile Paths in entire AD with logic

Answered Need to bulk modify all TS Profile/RDS Profile Paths in entire AD with logic

  • Friday, December 28, 2012 7:25 PM
     
     

    I had to replace a defective file server that was hosting roaming profiles.  I thought I could just swap it out and copy the data to a new server and create a static DNS A record with the old name pointing to the new server (I've done this for other servers successfully).  This time though some of my XP machines cannot view or access the shares on the new server using the old name (not been able to confirm if Win7 does this).  As a result their Home folders often do not get mounted, or they receive a warning the machine is using a local cached copy of the profile (no sync).

    I "fixed" this for one user by changing the home, profile and ts profile path names from \\servername\share\<username> to \\serverIP\share\<username>

    This worked, but I cannot do this effectively for 200+ accounts.

    I need a script that can read the values for the profile paths (from both the Profile and TS Profile tabs) and apply some logic before rewriting new values.

    If path value is blank, do nothing.

    If path value is \\servername\something, rewrite it to \\serverIP\something.

    if path value is \\serverIP\something, do nothing.

    Note: some of the folders have typos so I cannot change more than the server name to IP at this time.

    http://gallery.technet.microsoft.com/scriptcenter/9d494a81-79bc-4e99-b80a-ffaefc74ece0

    This was the closest script I've found but I need help filling in the logic parts (and looping through the whole AD for all accounts), I can find and graft in the missing code for the AD Profile path pieces.  I was thinking this may be possible to do using powershell but I'm not too confident in my PS skills yet (n00b).

    I looked at an AD Bulk Modify utility but it cannot see the TS profile properties.

    Note: at some point I plan to place the profiles into a DFS path, but not for a while yet.

All Replies

  • Friday, December 28, 2012 8:18 PM
    Moderator
     
     Answered Has Code

    I answered a similar question months ago with the following VBcript. This queries for users where the profilePath attribute includes the string "Server2". Then the script modifies profilePath for these users, replacing "\\Server2" with "\\Server3". You could do something very similar, replace "Server2" with "ServerName\Share" and "Server3" with "ServerIP\Share".

    Option Explicit

    Dim adoCommand, adoConnection, strBase, strFilter, strAttributes
    Dim objRootDSE, strDNSDomain, strQuery, adoRecordset, strDN
    Dim objUser, strPath, strNewPath

    ' Setup ADO objects.
    Set adoCommand = CreateObject("ADODB.Command")
    Set adoConnection = CreateObject("ADODB.Connection")
    adoConnection.Provider = "ADsDSOObject"
    adoConnection.Open "Active Directory Provider"
    Set adoCommand.ActiveConnection = adoConnection

    ' Search entire Active Directory domain.
    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")
    strBase = "<LDAP://" & strDNSDomain & ">"

    ' Filter on all user that have a profile on server2.
    strFilter = "(&(objectCategory=person)(objectClass=user)(profilePath=*server2*))"

    ' Comma delimited list of attribute values to retrieve.
    strAttributes = "distinguishedName,profilePath"

    ' Construct the LDAP syntax query.
    strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
    adoCommand.CommandText = strQuery
    adoCommand.Properties("Page Size") = 200
    adoCommand.Properties("Timeout") = 30
    adoCommand.Properties("Cache Results") = False

    ' Run the query.
    Set adoRecordset = adoCommand.Execute

    ' Enumerate the resulting recordset.
    Do Until adoRecordset.EOF
        ' Retrieve values.
        strDN = adoRecordset.Fields("distinguishedName").Value
        strPath = adoRecordset.Fields("profilePath").Value
        ' Escape any possible forward slash characters.
        strDN = Replace(strDN, "/", "\/")
        ' Bind to user object.
        Set objUser = GetObject("LDAP://" & strDN)
        ' Assign new profile path value.
        strNewPath = Replace(strPath, "\\Server2", "\\Server3")
        objUser.profilePath = strNewPath
        objUser.SetInfo
        ' Move to the next record in the recordset.
        adoRecordset.MoveNext
    Loop

    ' Clean up.
    adoRecordset.Close
    adoConnection.Close

    -----

    You can do similar for the TS Profile Path, where the AD attribute is msTSProfilePath. I would handle the two attributes separately. If you do them together in one script, then the filter would be:

    "(&(objectCategory=person)(objectClass=user)(|(profilePath=*server2*)(msTSProfilePath=*server2*)))"

    where the pipe symbol, "|", is the "Or" operator, so this filters on users where either profilePath or msTSProfiePath include the string "server2". Then to be safe, you should retrieve the values and check for blanks, since one or the other could be missing.


    Richard Mueller - MVP Directory Services

    • Marked As Answer by 247support Monday, December 31, 2012 10:06 PM
    •  
  • Friday, December 28, 2012 8:38 PM
     
     

    This is a warning to not pace profile paths on  the terminal server.  I have made a small cottage industry around fixing this.

    As soon as you get this resolve consider moving all profiles to an external file server.  This improves performance and provides instant recovery for a downed server.  You will never have an issue like this again.  It will also eliminate a large number of errors from the Event logs.


    Happy New Year ¯\_(ツ)_/¯

  • Monday, December 31, 2012 10:04 PM
     
     

    jrv,

    Yes, storing the profiles on the TS servers themselves is generally not a good idea (due to caching, etc).  In my case the profiles are stored on a dedicated (virtual) server to host just the profiles and we use folder redirection to ensure the roaming bits are as small as possible (most are under 10MB for the actual profile, even if the users has gigs of other documents).

  • Monday, December 31, 2012 10:37 PM
     
     

    I marked Richards answer as correct as it does what I asked for (thanks).  I'll very likely reference his answer for a future cleanup project.

    In my case I did a lot of digging and found out how to get the server to respond to the alias name AND allow simultaneous connections to the host name, alias name and/or IP number as originally desired.  By default windows does not allow this (try to connect to or map a drive using the netbios name and a second one to the same server using the IP and it should fail).

    Ref: http://blogs.technet.com/b/josebda/archive/2010/06/04/multiple-names-for-one-computer-consolidate-your-smb-file-servers-without-breaking-unc-paths.aspx

    Ref: http://support.microsoft.com/kb/281308

    I think what did the trick for me was to create the registry key listed in the MS kb to disable strict name checking (it does however require a reboot to take effect) and create a CNAME record (not an A record) for the old name pointing to the new server.  I did however during testing create the netdom aliases as noted in the first link and register a new SPN using the old name (cannot find the SPN link I used however, but I'm somewhat confident the SPN I created may not be necessary anyway).

    All these work now:

    \\newservername\share

    \\oldservername\share

    \\newserverIP\share

    I'm providing this info for anyone else who stumbles into the same problem.  I did not have to rewrite the AD properties now that the server can respond to all three connection types (I will correct the AD properties in the near future though to purge all references to the old name, perhaps once I create a suitable DFS tree to store it under).

  • Monday, December 31, 2012 11:14 PM
     
     

    One last thing I forgot to mention regarding the fix above, it only affects SMBv1.  I discovered that SMBv2 (or is it SMB2?) permits simultaneous aliased connections by default so 2008/Vista and above are unaffected and DNS CNAMES should be all that is needed to make things work.

    In my case the server was running 2008r2 but the affected stations were running XP, thus connecting using SMBv1.  If you only have Win7/2008r2 you probably aren't even aware of this issue because it works as expected (until you fire up that old laptop or PC running XP).

    In my case Windows 7 stations (we don't use Vista [spits on floor]) and 2008+ based servers had no problems, while XP/2003 stations had problems after the first connection was made.

    Example:

    net view newservername = returns list of shares

    net view aliasservername = failed "error 52 duplicate name exists on the network" (XP/2003)



    • Edited by 247support Monday, December 31, 2012 11:15 PM
    • Edited by 247support Monday, December 31, 2012 11:16 PM
    •