Copy NT user accounts between servers
I've created about 50 user accounts on a Windows 2003 Server, and I'd like to copy those accounts to a new server, is this possible? I'm not using Active Directory.
Patrick
Edit 1 : Thanks for the answers, however I should have been more specific in my original question. I'd like to copy the user accounts and maintain the existing passwords. Also, I'd like to copy the accounts between two servers across the internet and firewalls. Is it possible to simply backup and restore user accounts?
Solution 1:
The command "net user" will display a list of all user accounts. If you run this an pipe the output to a file you can then edit the file to convert it to a script to create the accounts of the new server. use "net help user" to see how to create accounts from a batch file. You'll probably have to do some manual tweaking of the accounts after creating them, but it's still a time saver compared to using the GUI.
NB you won't be able to extract the old passwords. If you don't know what your users passwords are you'll have to set them all to some default value then change them one by one.
JR
John's post has just reminded me: there's an applet from MS called AddUsers that helps with this sort of thing. See http://support.microsoft.com/kb/199878 for the details.
Solution 2:
Here's a VBscript program to copy local groups and user accounts from a source computer to a destination computer:
Option Explicit
Dim dictGroupsNotToCreate, dictPropertiesToCopy, dictUsersToIgnore, objNetwork
Dim colSourceGroups, colDestinationGroups, objSourceGroup, objDestinationGroup, objUser
Dim colSourceAccounts, colDestinationAccounts, objSourceUser, objDestinationUser, property
' Debugging
Const DEBUGGING = True
' Source and destination computers
Const SOURCE_COMPUTER = "PC00623"
Const DESTINATION_COMPUTER = "PC00619"
' Password to set on newly create user accounts
Const DEFAULT_PASSWORD = "rh1n0s!!!"
' Constants for comparison of accounts to ignore list
Const MATCH_EXACT = 1
Const MATCH_LEFT = 2
Set dictGroupsNotToCreate = CreateObject("Scripting.Dictionary")
dictGroupsNotToCreate.Add "Administrators", MATCH_EXACT
dictGroupsNotToCreate.Add "Backup Operators", MATCH_EXACT
dictGroupsNotToCreate.Add "Guests", MATCH_EXACT
dictGroupsNotToCreate.Add "Network Configuration Operators", MATCH_EXACT
dictGroupsNotToCreate.Add "Power Users", MATCH_EXACT
dictGroupsNotToCreate.Add "Remote Desktop Users", MATCH_EXACT
dictGroupsNotToCreate.Add "Replicator", MATCH_EXACT
dictGroupsNotToCreate.Add "Users", MATCH_EXACT
dictGroupsNotToCreate.Add "Debugger Users", MATCH_EXACT
dictGroupsNotToCreate.Add "HelpServicesGroup", MATCH_EXACT
' Properties of user accounts to copy
Set dictPropertiesToCopy = CreateObject("Scripting.Dictionary")
dictPropertiesToCopy.Add "Description", True
dictPropertiesToCopy.Add "FullName", True
dictPropertiesToCopy.Add "HomeDirDrive", True
dictPropertiesToCopy.Add "HomeDirectory", True
dictPropertiesToCopy.Add "LoginHours", True
dictPropertiesToCopy.Add "LoginScript", True
dictPropertiesToCopy.Add "Profile", True
' Accounts to ignore during copying
Set dictUsersToIgnore = CreateObject("Scripting.Dictionary")
dictUsersToIgnore.Add "SUPPORT_", MATCH_LEFT
dictUsersToIgnore.Add "IUSR_", MATCH_LEFT
dictUsersToIgnore.Add "IWAM_", MATCH_LEFT
dictUsersToIgnore.Add "Administrator", MATCH_EXACT
dictUsersToIgnore.Add "Guest", MATCH_EXACT
dictUsersToIgnore.Add "HelpAssistant", MATCH_EXACT
dictUsersToIgnore.Add "ASPNET", MATCH_EXACT
' Should this account be ignored
Function IgnoreObject(Name, dictNames)
Dim strToIgnore
IgnoreObject = False
For Each strToIgnore in dictNames
' Match Exact
If (dictNames.Item(strToIgnore) = MATCH_EXACT) and (UCase(Name) = UCase(strToIgnore)) Then
IgnoreObject = True
Exit Function
End If
' Match left
If (dictNames.Item(strToIgnore) = MATCH_LEFT) and (Left(UCase(Name), Len(strToIgnore)) = UCase(strToIgnore)) Then
IgnoreObject = True
Exit Function
End If
Next' strToIgnore
End Function
Set objNetwork = CreateObject("Wscript.Network")
' Get groups on source computer and loop through them, copying as necessary
Set colSourceGroups = GetObject("WinNT://" & SOURCE_COMPUTER)
Set colDestinationGroups = GetObject("WinNT://" & DESTINATION_COMPUTER)
colSourceGroups.Filter = Array("group")
For Each objSourceGroup in colSourceGroups
If IgnoreObject(objSourceGroup.Name, dictGroupsNotToCreate) = False then
If (DEBUGGING) Then WScript.Echo "Creating Group: " & objSourceGroup.Name
Set objDestinationGroup = colDestinationGroups.Create("group", objSourceGroup.Name)
objDestinationGroup.Put "Description", objSourceGroup.Get("Description")
objDestinationGroup.SetInfo
Else
If (DEBUGGING) Then WScript.Echo "Ignoring Group: " & objSourceGroup.Name
End If
Next ' objSourceGroup
' Get accounts on source computer and loop through them, copying as necessary
Set colSourceAccounts = GetObject("WinNT://" & SOURCE_COMPUTER)
set colDestinationAccounts = GetObject("WinNT://" & DESTINATION_COMPUTER)
colSourceAccounts.Filter = Array("user")
For Each objSourceUser In colSourceAccounts
If IgnoreObject(objSourceUser.Name, dictUsersToIgnore) = False Then
If (DEBUGGING) Then WScript.Echo "Copying account: " & objSourceUser.Name
On Error Resume Next
Set objDestinationUser = colDestinationAccounts.Create("user", objSourceUser.Name)
objDestinationUser.SetPassword DEFAULT_PASSWORD
objDestinationUser.SetInfo
' Copy properties from source user to destination user
For Each property in dictPropertiesToCopy
If (DEBUGGING) then WScript.Echo " Copying property " & property & " (" & objSourceUser.Get(property) & ")"
objDestinationUser.Put property, objSourceUser.Get(property)
objDestinationUser.SetInfo
Next ' property
' Put user into destination groups
For Each objSourceGroup In colSourceGroups
For Each objUser In objSourceGroup.Members
If UCase(objUser.Name) = Ucase(objSourceUser.Name) Then
If (DEBUGGING) Then WScript.Echo "Adding user " & objSourceUser.Name & " to group " & objSourceGroup.Name
Set objDestinationGroup = GetObject("WinNT://" & DESTINATION_COMPUTER & "/" & objSourceGroup.Name & ",group")
objDestinationGroup.Add(objDestinationUser.aDSPath)
Else
If (DEBUGGING) Then WScript.Echo "User " & objSourceUser.Name & " is not a member of group " & objSourceGroup.Name
End If
Next ' objUser
Next 'objSourceGroup
Else
If (DEBUGGING) Then WScript.Echo "Ignoring account: " & objSourceUser.Name
End If
Next ' objSourceUser
A quick tour:
- Set the SOURCE_COMPUTER and DESTINATION_COMPUTER names
- Set the DEFAULT_PASSWORD (which will be assigned to the newly created user accounts)
- Add any local group names that should not be created on the destination computer to the dictGroupsNotToCreate list. MATCH_EXACT means that the name of the group is matched exactly. MATCH_LEFT means that only the leftmost portion of the group name will be matched (i.e. imagine that the name match has a "*" after it).
- Add any local user names that should not be created on the destination computer to the dictUsersToIgnore LIST. MATCH_EXACT and MATCH_LEFT have the same meanings as with the dictGroupsNotToCreate list (i.e. "IUSR_" with MATCH_LEFT means that any user account starting with "IUSR_" will not be created on the destination computer).
You must execute this script with credentials that have rights to create accounts on the destination computer.
The properties copied for user accounts, by default, are listed in the dictPropertiesToCopy list. I chose the most common properties.
The script has been tested fairly well, but I haven't used it in a production environment. It makes NO changes to the source server, so you can run it w/o fear of damaging your source server.
(No, the group population algorith isn't effiicent in the slightest. If that bothers you then you know enough already to re-implement it better... >smile<)