Someone decides we need to change the farm from one environment to a new one completely different with a new AD and in a new city.

Fantastic?
Step One:
Get all of the users from the old farm in an XML file or something really high tech (a csv could work too).
static void Main(string[] args) { using (SPSite site = new SPSite(args[0])) { using (SPWeb web = site.OpenWeb()) { XElement users = new XElement("Users"); foreach (SPUser user in web.SiteUsers) { XElement xmlUser = new XElement("User"); xmlUser.Add(new XAttribute("Name", user.Name)); xmlUser.Add(new XAttribute("LoginName", user.LoginName)); xmlUser.Add(new XAttribute("ID", user.ID)); users.Add(xmlUser); } users.Save("SiteUsers.xml"); } } Console.WriteLine("\nProcess finished..."); Console.ReadLine(); }
Step Two:
Make sure all the users you need are in the new AD. As you have a list in XML you can pass it to someone with privileges in the AD.
Step Three:
Ensure the users in SharePoint, add them to a group with reading permissions and then iterate through all the items in the list changing the users from the old domain to the users in the new one.
static void Main(string[] args) { XElement users = XElement.Load("SiteUsers.xml"); string newDomain = "XXXXXXXX"; string ListName = string.Empty; if (args.Length == 2) ListName = "Stratex Framework"; else ListName = args[2]; //Args are SiteUrl VisitorsGroup ListName using (SPSite site = new SPSite(args[0])) { using (SPWeb web = site.OpenWeb()) { SPList listToUpdate = web.Lists[ListName]; Dictionary<string, SPUser> NewUsers = new Dictionary<string, SPUser>(); foreach (XElement user in users.Descendants("User")) { string LoginName = FixDomain(user.Attribute("LoginName").Value, newDomain); SPUser spUser = null; try { //We try to ensure all the users from the XML file. We'll probably need them spUser = web.EnsureUser(LoginName); } catch { Logger.WriteLine("The user {0} could not be found.", LoginName); } if (spUser != null) { SPGroup viewers = web.Groups[args[1]]; viewers.AddUser(spUser); //Finally we add them to a group with read permissions //We can worry about restricting this further after the migration if (!NewUsers.ContainsKey(LoginName)) NewUsers.Add(user.Attribute("ID").Value, spUser); } } web.Update(); UpdateUsersInList(listToUpdate, NewUsers); } } Logger.WriteLine("\nProcess finished..."); Console.ReadLine(); } private static void UpdateUsersInList(SPList list, Dictionary<string, SPUser> NewUsers) { int itemsInList = list.ItemCount; Logger.WriteLine("Updating users at {0}. {1} items.", list.Title, itemsInList.ToString()); SPQuery qry = new SPQuery(); qry.ViewAttributes = "Scope=\"RecursiveAll\""; SPListItemCollection allItems = list.GetItems(qry); int count = 0; UpdateCount(count++, itemsInList); foreach (SPListItem item in allItems) { try { bool changed = false; SPFieldCollection allFields; //If the item has content type it has usualy less fields if (item.ContentType == null) allFields = item.Fields; else allFields = item.ContentType.Fields; foreach (SPField field in allFields) { if (field is SPFieldUser) changed = ChangeUserToNewDomain(item, field, NewUsers) || changed; } changed = ChangeUserToNewDomain(item, item.Fields.GetFieldByInternalName("Author"), NewUsers) || changed; changed = ChangeUserToNewDomain(item, item.Fields.GetFieldByInternalName("Editor"), NewUsers) || changed; if (changed) item.SystemUpdate(false); //if the item has not been changed we won't update it to save time } catch (Exception ex) { Logger.WriteLine("Failed to update item {0}. Exception {1}", item.Title, ex.Message); } UpdateCount(count++, itemsInList); } UpdateCount(count++, 0); } private static bool ChangeUserToNewDomain(SPListItem item, SPField field, Dictionary<string, SPUser> NewUsers) { bool changed = false; string fieldContent = item[field.InternalName] == null ? null : item[field.InternalName].ToString(); if (string.IsNullOrEmpty(fieldContent)) return false; List<string> oldUserIds = GetUserIDs(fieldContent.Split(new string[] { ";#" }, StringSplitOptions.RemoveEmptyEntries)); if (oldUserIds.Count == 1) { //The field has only one user in it SPFieldUserValue foundUser = FindUser(NewUsers, oldUserIds[0]); if (foundUser != null) { item[field.InternalName] = foundUser; changed = true; } } else if (oldUserIds.Count > 1) { //The field has several users in it SPFieldUserValueCollection usersInField = new SPFieldUserValueCollection(); foreach (string oldUser in oldUserIds) { SPFieldUserValue foundUser = FindUser(NewUsers, oldUser); if (foundUser != null) usersInField.Add(foundUser); } if (usersInField.Count > 0) { item[field.InternalName] = usersInField; changed = true; } } return changed; } private static List<string> GetUserIDs(string[] UserTokens) { //We do not care about the login name. The ID is gold List<string> result = new List<string>(); if (UserTokens.Length > 0) { for (int i = 0; i < UserTokens.Length; i++) { int id; if (i % 2 == 0 && int.TryParse(UserTokens[i], out id)) result.Add(id.ToString()); } } return result; } private static SPFieldUserValue FindUser(Dictionary<string, SPUser> NewUsers, string oldUser) { SPUser foundUser = null; if (NewUsers.ContainsKey(oldUser)) foundUser = NewUsers[oldUser]; else { //If we can't find the ID of the user we will still try with the login or even with the Display Name foreach (SPUser newUser in NewUsers.Values) { if (newUser.Name == oldUser || newUser.LoginName == oldUser) { foundUser = newUser; break; } } } if (foundUser != null) return new SPFieldUserValue(foundUser.ParentWeb, foundUser.ID, foundUser.Name); else return null; } private static string FixDomain(string loginName, string newDomain) { //Here we change the users from XXXXX\\User to YYYYY\\User //The source domain was claim based if (loginName.Contains("|")) loginName = loginName.Split('|')[1]; string[] tokens = loginName.Split('\\'); tokens[0] = newDomain; return string.Join("\\", tokens); } private static void UpdateCount(int currentItem, int itemsInList) { int percentage; if (currentItem == 0) percentage = 0; else if (itemsInList == 0) percentage = 100; else { //We will only change the value every 10 times to make the process faster. if (currentItem % 10 != 0) return; percentage = currentItem * 100 / itemsInList; } Console.Write("\r"); if (percentage >= 0 && percentage < 10) Console.Write(" "); else if (percentage >= 10 && percentage < 100) Console.Write(" "); Console.Write("{0}%", percentage); }
No comments:
Post a Comment