using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.AccountManagement;
using Microsoft.Xrm.Client;
using Microsoft.Xrm.Client.Services;
using Microsoft.Xrm.Sdk;
using System.DirectoryServices;
namespace UpdateCRM2011UsersFromAD
{
class Program
{
static Dictionary<string, string> xRMToADFields = new Dictionary<string, string>();
/// <summary>
/// Setup which xRM fields map to which AD fields
/// </summary>
public static void SetupFieldMapping()
{
xRMToADFields.Add("firstname", "givenName");
xRMToADFields.Add("lastname", "sn");
xRMToADFields.Add("internalemailaddress", "mail");
xRMToADFields.Add("title", "title");
xRMToADFields.Add("address1_telephone1", "telephoneNumber");
xRMToADFields.Add("mobilephone", "mobile");
xRMToADFields.Add("address1_fax", "facsimileTelephoneNumber");
xRMToADFields.Add("address1_line1", "streetAddress");
xRMToADFields.Add("address1_city", "l");
xRMToADFields.Add("address1_stateorprovince", "st");
xRMToADFields.Add("address1_postalcode", "postalCode");
xRMToADFields.Add("address1_country", "co");
}
/// <summary>
/// Finds differences in email between AD and crm 2011 user record.
/// Argument0: CRM 2011 Url ex. http://crm/crmorg
/// Argument1: Run mode (S)can, (P)rompt, or (U)pdate
/// </summary>
/// <param name="args"></param>
public static void Main(string[] args)
{
Console.WriteLine("Initializing...");
SetupFieldMapping();
// Grab the Crm Url from the first line argument. Ex. http://crmservername/crmorgname
string crmUrl = args[0];
// Grab the running mode (S = scan mode, P = prompt mode, U = update mode)
// scan mode only displays the differences
// prompt mode prompts you before updating the current record
// and update mode updates everything without
string runMode;
// Default it to Prompt mode if not entered
if (args.Count() > 1)
runMode = args[1];
else
runMode = "P";
runMode = runMode.ToUpper();
string crmConnectionString = "Url=" + crmUrl;
var systemConnection = CrmConnection.Parse(crmConnectionString);
using (var crmContext = new CrmOrganizationServiceContext(systemConnection))
{
// Disable caching
crmContext.TryAccessCache(cache => cache.Mode = OrganizationServiceCacheMode.Disabled);
// Get all the non disabled users
var enabledUsers = (from u in crmContext.CreateQuery("systemuser") where u.GetAttributeValue<bool>("isdisabled") == false select u);
// Grab the domain context
Dictionary<string, string> modifiedFields = new Dictionary<string, string>();
foreach (var currentEnabledUser in enabledUsers)
{
crmContext.Detach(currentEnabledUser);
// Make sure the user record is valid and has a domain name.
if (!string.IsNullOrWhiteSpace(currentEnabledUser.GetAttributeValue<string>("domainname")))
{
// Get System User's Domain name and email address.
string userDomainName = currentEnabledUser.GetAttributeValue<string>("domainname");
string domainName = userDomainName.Substring(0, userDomainName.IndexOf('\\'));
PrincipalContext domain = new PrincipalContext(ContextType.Domain, domainName);
// Grab the crm system user's Active Directory object
UserPrincipal ADUserRecord = UserPrincipal.FindByIdentity(domain, userDomainName);
if (ADUserRecord != null)
{
bool isUserModified = false;
Entity userObject = new Entity("systemuser");
userObject.Id = currentEnabledUser.Id;
crmContext.Attach(userObject);
// Open up the actual directory entry object which contains much more data than a simple user principal object
using (DirectoryEntry underlyingADRecord = (DirectoryEntry)ADUserRecord.GetUnderlyingObject())
{
// Look through each field, if they do not match prompt/or update
foreach (var currentProperty in xRMToADFields)
{
// Get the AD and the CRM values for the current property.
string adValue = underlyingADRecord.Properties.Contains(currentProperty.Value)
? underlyingADRecord.Properties[currentProperty.Value].Value.ToString()
: "";
string crmValue = currentEnabledUser.Attributes.Contains(currentProperty.Key)
? currentEnabledUser.GetAttributeValue<string>(currentProperty.Key)
: "";
// Check if any of the fields are modified if so turn the flag to true without overriding it.
if ((currentEnabledUser.GetAttributeValue<string>(currentProperty.Key) == null && !string.IsNullOrWhiteSpace(adValue))
||
adValue.ToLower() != crmValue.ToLower())
{
// It is the first modified field of a new user so display the user we are processing.
if (!isUserModified)
{
Console.WriteLine();
Console.WriteLine("Modifications to the user: {0}", userDomainName);
Console.WriteLine();
}
// Display the fields that need an update
Console.WriteLine("Old {0}: {1}{3}New {0}: {2}{3}",
currentProperty.Key,
crmValue,
adValue,
Environment.NewLine);
// Put the changes to the User Object
userObject[currentProperty.Key] = adValue;
// Flag that user record has been modified
isUserModified |= true;
}
}
// If the record has modifications that we need to push and it is not scan mode run the update block
if (isUserModified && runMode != "S")
{
// Try prompting the user if the runmode is not on update mode
if (runMode != "U")
{
// Prompt the user if we should update this record.
Console.WriteLine("Would you like to update the record Y/N/U U for Updating all the users.");
var response = Console.ReadLine();
response = response.ToUpper().ElementAt(0).ToString();
// if they said U switch the run mode to update so they don't get consequent prompts.
if (response == "U")
runMode = "U";
// If it is not a positive response skip updating the record, start processing the next record
if (response != "U" && response != "Y")
continue;
}
// If the code reached here it means we want to push the user object to the crm server
try
{
crmContext.UpdateObject(userObject);
crmContext.SaveChanges();
Console.WriteLine("Updated User: {0}", userDomainName);
}
catch (Exception ex)
{
Console.WriteLine("Error on user {0]", userDomainName);
Console.WriteLine(ex.Message);
}
Console.WriteLine();
}
}
crmContext.Detach(userObject);
}
else
Console.WriteLine("Warning: User {0} no longer exists in AD.", userDomainName);
}
}
}
Console.WriteLine("Run completed, press any key to continue...");
Console.ReadKey();
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.AccountManagement;
using Microsoft.Xrm.Client;
using Microsoft.Xrm.Client.Services;
using Microsoft.Xrm.Sdk;
using System.DirectoryServices;
namespace UpdateCRM2011UsersFromAD
{
class Program
{
static Dictionary<string, string> xRMToADFields = new Dictionary<string, string>();
/// <summary>
/// Setup which xRM fields map to which AD fields
/// </summary>
public static void SetupFieldMapping()
{
xRMToADFields.Add("firstname", "givenName");
xRMToADFields.Add("lastname", "sn");
xRMToADFields.Add("internalemailaddress", "mail");
xRMToADFields.Add("title", "title");
xRMToADFields.Add("address1_telephone1", "telephoneNumber");
xRMToADFields.Add("mobilephone", "mobile");
xRMToADFields.Add("address1_fax", "facsimileTelephoneNumber");
xRMToADFields.Add("address1_line1", "streetAddress");
xRMToADFields.Add("address1_city", "l");
xRMToADFields.Add("address1_stateorprovince", "st");
xRMToADFields.Add("address1_postalcode", "postalCode");
xRMToADFields.Add("address1_country", "co");
}
/// <summary>
/// Finds differences in email between AD and crm 2011 user record.
/// Argument0: CRM 2011 Url ex. http://crm/crmorg
/// Argument1: Run mode (S)can, (P)rompt, or (U)pdate
/// </summary>
/// <param name="args"></param>
public static void Main(string[] args)
{
Console.WriteLine("Initializing...");
SetupFieldMapping();
// Grab the Crm Url from the first line argument. Ex. http://crmservername/crmorgname
string crmUrl = args[0];
// Grab the running mode (S = scan mode, P = prompt mode, U = update mode)
// scan mode only displays the differences
// prompt mode prompts you before updating the current record
// and update mode updates everything without
string runMode;
// Default it to Prompt mode if not entered
if (args.Count() > 1)
runMode = args[1];
else
runMode = "P";
runMode = runMode.ToUpper();
string crmConnectionString = "Url=" + crmUrl;
var systemConnection = CrmConnection.Parse(crmConnectionString);
using (var crmContext = new CrmOrganizationServiceContext(systemConnection))
{
// Disable caching
crmContext.TryAccessCache(cache => cache.Mode = OrganizationServiceCacheMode.Disabled);
// Get all the non disabled users
var enabledUsers = (from u in crmContext.CreateQuery("systemuser") where u.GetAttributeValue<bool>("isdisabled") == false select u);
// Grab the domain context
Dictionary<string, string> modifiedFields = new Dictionary<string, string>();
foreach (var currentEnabledUser in enabledUsers)
{
crmContext.Detach(currentEnabledUser);
// Make sure the user record is valid and has a domain name.
if (!string.IsNullOrWhiteSpace(currentEnabledUser.GetAttributeValue<string>("domainname")))
{
// Get System User's Domain name and email address.
string userDomainName = currentEnabledUser.GetAttributeValue<string>("domainname");
string domainName = userDomainName.Substring(0, userDomainName.IndexOf('\\'));
PrincipalContext domain = new PrincipalContext(ContextType.Domain, domainName);
// Grab the crm system user's Active Directory object
UserPrincipal ADUserRecord = UserPrincipal.FindByIdentity(domain, userDomainName);
if (ADUserRecord != null)
{
bool isUserModified = false;
Entity userObject = new Entity("systemuser");
userObject.Id = currentEnabledUser.Id;
crmContext.Attach(userObject);
// Open up the actual directory entry object which contains much more data than a simple user principal object
using (DirectoryEntry underlyingADRecord = (DirectoryEntry)ADUserRecord.GetUnderlyingObject())
{
// Look through each field, if they do not match prompt/or update
foreach (var currentProperty in xRMToADFields)
{
// Get the AD and the CRM values for the current property.
string adValue = underlyingADRecord.Properties.Contains(currentProperty.Value)
? underlyingADRecord.Properties[currentProperty.Value].Value.ToString()
: "";
string crmValue = currentEnabledUser.Attributes.Contains(currentProperty.Key)
? currentEnabledUser.GetAttributeValue<string>(currentProperty.Key)
: "";
// Check if any of the fields are modified if so turn the flag to true without overriding it.
if ((currentEnabledUser.GetAttributeValue<string>(currentProperty.Key) == null && !string.IsNullOrWhiteSpace(adValue))
||
adValue.ToLower() != crmValue.ToLower())
{
// It is the first modified field of a new user so display the user we are processing.
if (!isUserModified)
{
Console.WriteLine();
Console.WriteLine("Modifications to the user: {0}", userDomainName);
Console.WriteLine();
}
// Display the fields that need an update
Console.WriteLine("Old {0}: {1}{3}New {0}: {2}{3}",
currentProperty.Key,
crmValue,
adValue,
Environment.NewLine);
// Put the changes to the User Object
userObject[currentProperty.Key] = adValue;
// Flag that user record has been modified
isUserModified |= true;
}
}
// If the record has modifications that we need to push and it is not scan mode run the update block
if (isUserModified && runMode != "S")
{
// Try prompting the user if the runmode is not on update mode
if (runMode != "U")
{
// Prompt the user if we should update this record.
Console.WriteLine("Would you like to update the record Y/N/U U for Updating all the users.");
var response = Console.ReadLine();
response = response.ToUpper().ElementAt(0).ToString();
// if they said U switch the run mode to update so they don't get consequent prompts.
if (response == "U")
runMode = "U";
// If it is not a positive response skip updating the record, start processing the next record
if (response != "U" && response != "Y")
continue;
}
// If the code reached here it means we want to push the user object to the crm server
try
{
crmContext.UpdateObject(userObject);
crmContext.SaveChanges();
Console.WriteLine("Updated User: {0}", userDomainName);
}
catch (Exception ex)
{
Console.WriteLine("Error on user {0]", userDomainName);
Console.WriteLine(ex.Message);
}
Console.WriteLine();
}
}
crmContext.Detach(userObject);
}
else
Console.WriteLine("Warning: User {0} no longer exists in AD.", userDomainName);
}
}
}
Console.WriteLine("Run completed, press any key to continue...");
Console.ReadKey();
}
}
}
No comments:
Post a Comment