Migrating FPSE Roles Between Servers
I ran into one of those strange situations the other day where you feel like you've been doing the same thing on your computer at some time in the distant past - kind of like déjà vu for geeks. In this specific case, I was moving some web sites that I am hosting for other people that still use FPSE from an older physical server to a new virtual server that is hosted through Hyper-V. (I'm also trying to convert them all to WebDAV, but that's another story.)
Anyway, I had dozens of custom FPSE roles set up for each of those sites that I didn't want to manually replicate on the new server. Unfortunately, FPSE doesn't have a way to migrate the roles from one server to another. All of those FPSE-related roles are kept in local groups with cryptic names like OWS_nnnnn_xxxxx, so I started thinking, "If only I could write a script that could migrate the OWS_nnnnn_xxxxx groups between the two servers... "
Then it dawned on me - I had written such a script several years ago! (Now if only I could find it...) Like many people that write code, I'm something of a code packrat - I tend to keep all of my old code around somewhere, just in case. Sparing you the details of my long search, I eventually found the script that I was looking for, and I thought that it would make a nice blog because I'm sure that someone else may need to migrate their FPSE roles.
Here's the script and a brief description of what script it will do:
- Create ADSI objects for the source and destination servers.
- Loop through the ADSI objects and only looks for groups.
- Note: You could also use an
object.Filter
statement for this. - You will obviously need to update the server names for your source and destination servers.
- Note: You could also use an
- Compare each group name with the group stub and only process those groups that match the stub.
- By way of explanation, FPSE role groups have names like OWS_nnnnn_xxxxx, where nnnnn is a simple numeric hash that identifies the site, and the xxxxx denotes the individual FPSE role like admin, browser, author, etc.
- The script uses the OWS_nnnnn stub and will copy all of the role groups that it finds. For example: OWS_12345_admin, OWS_12345_author, OWS_12345_browser, etc.
- In the code I used OWS_nnnnn for the stub, so you would have to replace nnnnn with the numbers that you see in the list of groups using Computer Management on the source computer.
- Determine if the group exists on the destination server, and creates it if it doesn't already exist.
- Loop through the list of users in the group on the source server and adds those same users to the group on the destination server.
- Note: This will fail for any local users that were used on the source server that do not exist on the destination server. I only used domain accounts, so I didn't run into that problem.
Some additional notes:
- The person that runs this code must be an administrator on each server.
- The two computers must be on the same network or the ADSI calls will fail.
With that in mind, here's the script code:
Option Explicit
On Error Resume Next
Dim objComputer1, objGroup1
Dim objComputer2, objGroup2
Dim objOBJECT
Dim objUSER
Dim strGroupName
Dim strGroupDesc
Const ERROR_SUCCESS = 0
' Note: update the following server names.
Const strComputer1 = "SERVER1"
Const strComputer2 = "SERVER2"
' Note: update the following group stub.
Const strGroupStub = "OWS_nnnnn"
' ----------------------------------------------------------------------
Set objComputer1 = GetObject("WinNT://" & strComputer1 & ",computer")
If CLng(Err.Number) <> ERROR_SUCCESS Then HandleError
Set objComputer2 = GetObject("WinNT://" & strComputer2 & ",computer")
If CLng(Err.Number) <> ERROR_SUCCESS Then HandleError
For Each objOBJECT in objComputer1
If UCase(objOBJECT.Class) = "GROUP" Then
strGroupName = objOBJECT.Name
If UCase(Left(strGroupName,Len(strGroupStub))) = UCase(strGroupStub) Then
Err.Clear : Set objGroup1 = GetObject("WinNT://" & strComputer1 & "/" & strGroupName & ",group")
If CLng(Err.Number) <> ERROR_SUCCESS Then HandleError
strGroupDesc = objGroup1.Description
WScript.Echo "Copying " & strGroupName & "..."
Err.Clear : Set objGroup2 = GetObject("WinNT://" & strComputer2 & "/" & strGroupName & ",group")
If CLng(Err.Number) <> ERROR_SUCCESS Then
If CLng(Err.Number) <> -2147022676 Then
HandleError
Else
Err.Clear : Set objGroup2 = objComputer2.Create("group",strGroupName)
If CLng(Err.Number) <> ERROR_SUCCESS Then HandleError
Err.Clear : objGroup2.SetInfo
If CLng(Err.Number) <> ERROR_SUCCESS Then HandleError
Err.Clear : objGroup2.Description = strGroupDesc
If CLng(Err.Number) <> ERROR_SUCCESS Then HandleError
Err.Clear : objGroup2.SetInfo
If CLng(Err.Number) <> ERROR_SUCCESS Then HandleError
End If
End If
For Each objUSER in objGroup1.Members
WScript.Echo vbTab & "Adding " & objUSER.Name
Err.Clear : objGroup2.Add objUSER.ADsPath
If CLng(Err.Number) <> ERROR_SUCCESS And CLng(Err.Number) <> -2147023518 Then HandleError
Err.Clear : objGroup2.SetInfo
If CLng(Err.Number) <> ERROR_SUCCESS Then HandleError
Next
Set objGroup1 = Nothing
Set objGroup2 = Nothing
End If
End If
Next
' ----------------------------------------------------------------------
Sub HandleError()
WScript.Echo vbCrLf & "FATAL ERROR:"
WScript.Echo vbTab & "Number: " & CLng(Err.Number) & " (0x" & Hex(CLng(Err.Number)) & ")"
WScript.Echo vbTab & "Description: " & Err.Description
WScript.Quit
End Sub
As usual, all of the normal caveats like "this code is totally unsupported" will apply, but I've used this code with great success on several severs over the years. The great thing about this code is that it's non-destructive because it doesn't delete anything on the source server - it only creates groups on the destination server.
You can also use Const strGroupStub = "OWS_"
to migrate all FPSE role groups from one server to another, but that's a major operation. With that in mind, I'd try it out on a single FPSE site using "OWS_nnnnn" as a stub before trying out a full server by using "OWS_ " as a stub; the latter is very time-consuming and CPU-intensive.
Comments
Anonymous
January 17, 2010
very interesting article. If I manage to make it work it could save me hours of work. Unfortunately I still do not understand how do you link the newly created local groups to the FPex in the target server. The groups are all there but the ntfs acl of the folders (I migrated the website via IISMT) are still referring to a non-existent GUID. How can I reestablish the links? Thanks, Roberto.Anonymous
January 18, 2010
The comment has been removed