User Profile Properties

Posted on Posted in SharePoint 2007, STSADM Commands

After running our upgrade and inspecting the user profile properties on the SSP that we created it was quickly discovered that some properties needed to be modified. Some of the changes were as simple as determining whether or not the property should be visible on the profile page or whether the user should be allowed to edit the property and some of them needed to be mapped to the corresponding field in Active Directory.

As part of my upgrade script I needed to make sure that these fields were set appropriately. You can set these fields via the browser by going to the SSP administration site and selecting "User profiles and properties" under the "User Profiles and My Sites" section. From there click "View profile properties" to see and edit the various properties.

In order to make these changes in batch during the upgrade I created two commands – the first was just to help me debug and is useful if you wish to get a dump of all the existing properties: gl-enumprofileproperties. The second command actually handles the editing of the properties: gl-editprofileproperty. The code for this is similar in nature to that of the gl-enumprofileprivacypolicies and gl-setprofileprivacypolicy commands – in fact I started with the code from those commands as a template and modified as needed. The one simplification was that I now only had one place to look for objects of interest – UserProfileConfigManager. The commands I created are detailed below.

1. gl-enumprofileproperties

This command works exactly like the gl-enumprofileprivacypolicies command but removes the privacy policy objects and adds additional information specific to the Property object:

   1: public override int Run(string command, StringDictionary keyValues, out string output)
   2: {
   3:  output = string.Empty;
   5:  InitParameters(keyValues);
   7:  ServerContext serverContext = ServerContext.GetContext(Params["sspname"].Value);
   8:  UserProfileConfigManager manager = new UserProfileConfigManager(serverContext);
   9:  PropertyCollection properties = manager.GetProperties();
  11:  StringBuilder sb = new StringBuilder();
  13:  XmlTextWriter xmlWriter = new XmlTextWriter(new StringWriter(sb));
  14:  xmlWriter.Formatting = Formatting.Indented;
  16:  xmlWriter.WriteStartElement("Properties");
  17:  xmlWriter.WriteAttributeString("ssp", Params["sspname"].Value);
  19:  foreach (Property item in properties)
  20:  {
  21:   AddXml(xmlWriter, item, manager);
  22:  }
  24:  xmlWriter.WriteEndElement();
  25:  xmlWriter.Flush();
  27:  output += sb.ToString();
  29:  if (Params["outputfile"].UserTypedIn)
  30:  {
  31:   File.WriteAllText(Params["outputfile"].Value, output);
  32:   output = string.Empty;
  33:  }
  35:  return 1;
  36: }
  38: private static void AddXml(XmlTextWriter xmlWriter, Property item, UserProfileConfigManager manager)
  39: {
  40:  xmlWriter.WriteStartElement("Property");
  42:  xmlWriter.WriteElementString("Name", item.Name);
  43:  xmlWriter.WriteElementString("AllowPolicyOverride", item.AllowPolicyOverride.ToString());
  44:  xmlWriter.WriteStartElement("ChoiceList");
  45:  if (item.ChoiceList != null)
  46:  {
  47:   foreach (string s in item.ChoiceList.GetAllTerms(true))
  48:   {
  49:    xmlWriter.WriteElementString("Choice", s);
  50:   }
  51:  }
  52:  xmlWriter.WriteEndElement();
  53:  xmlWriter.WriteElementString("ChoiceType", item.ChoiceType.ToString());
  54:  xmlWriter.WriteElementString("DefaultPrivacy", item.DefaultPrivacy.ToString());
  55:  xmlWriter.WriteElementString("Description", item.Description);
  56:  xmlWriter.WriteElementString("DisplayName", item.DisplayName);
  57:  xmlWriter.WriteElementString("DisplayOrder", item.DisplayOrder.ToString());
  58:  xmlWriter.WriteElementString("IsAdminEditable", item.IsAdminEditable.ToString());
  59:  xmlWriter.WriteElementString("IsAlias", item.IsAlias.ToString());
  60:  xmlWriter.WriteElementString("IsColleagueEventLog", item.IsColleagueEventLog.ToString());
  61:  xmlWriter.WriteElementString("IsImported", item.IsImported.ToString());
  62:  xmlWriter.WriteElementString("IsMultivalued", item.IsMultivalued.ToString());
  63:  xmlWriter.WriteElementString("IsReplicable", item.IsReplicable.ToString());
  64:  xmlWriter.WriteElementString("IsRequired", item.IsRequired.ToString());
  65:  xmlWriter.WriteElementString("IsSearchable", item.IsSearchable.ToString());
  66:  xmlWriter.WriteElementString("IsSection", item.IsSection.ToString());
  67:  xmlWriter.WriteElementString("IsSystem", item.IsSystem.ToString());
  68:  xmlWriter.WriteElementString("IsUpgrade", item.IsUpgrade.ToString());
  69:  xmlWriter.WriteElementString("IsUpgradePrivate", item.IsUpgradePrivate.ToString());
  70:  xmlWriter.WriteElementString("IsUserEditable", item.IsUserEditable.ToString());
  71:  xmlWriter.WriteElementString("IsVisibleOnEditor", item.IsVisibleOnEditor.ToString());
  72:  xmlWriter.WriteElementString("IsVisibleOnViewer", item.IsVisibleOnViewer.ToString());
  73:  xmlWriter.WriteElementString("Length", item.Length.ToString());
  74:  xmlWriter.WriteElementString("ManagedPropertyName", item.ManagedPropertyName);
  75:  xmlWriter.WriteElementString("MaximumShown", item.MaximumShown.ToString());
  76:  xmlWriter.WriteElementString("PrivacyPolicy", item.PrivacyPolicy.ToString());
  77:  xmlWriter.WriteElementString("Separator", item.Separator.ToString());
  78:  xmlWriter.WriteElementString("Type", item.Type);
  79:  xmlWriter.WriteElementString("URI", item.URI);
  80:  xmlWriter.WriteElementString("UserOverridePrivacy", item.UserOverridePrivacy.ToString());
  82:  xmlWriter.WriteStartElement("ImportMapping");
  83:  PropertyMapCollection propertyMapping = manager.GetDataSource().PropertyMapping;
  84:  PropertyMap map = propertyMapping[item.Name];
  86:  if (map != null)
  87:  {
  88:   xmlWriter.WriteElementString("DSPropName", map.DSPropName);
  89:   xmlWriter.WriteElementString("ConnectionName", map.ConnectionName);
  90:   xmlWriter.WriteElementString("AssociationName", map.AssociationName);
  91:  }
  92:  xmlWriter.WriteEndElement();
  94:  xmlWriter.WriteEndElement();
  95: }

The syntax of the command can be seen below:

C:\>stsadm -help gl-enumprofileproperties

stsadm -o gl-enumprofileproperties

Lists the user profile properties associated with the SSP.

        -sspname <name of the SSP>
        [-outputfile <file to output results to>]

Here’s an example of how to output all the profile information to a file:

stsadm –o gl-enumprofileproperties -sspname "SSP1" -outputfile "c:\properties.xml"

Running the above command will produce results similar to the following (I’ve abbreviated the output for the sake of space):

<Properties ssp="SSP1">
    <ChoiceList />
    <Description />
    <DisplayName>College Major</DisplayName>
    <ImportMapping />

2. gl-editprofileproperty

This command actually gave me a bit of trouble because I couldn’t get large parts of the internal Microsoft code disassembled to see what exactly they were doing (Reflector seems to choke on large chunks of the SharePoint API). The piece that gave me the most trouble is the mapping of a property to a data sources fields. If you have only one connection (Active Directory specifically is what I tested against) then the code and command is really simple. What I’m uncomfortable with is the use of the connectionname and associationname parameters which I use to build the property map based on what I could gleam from the IL code. I do feel like there’s something I’m missing with the usage of these properties (PropertyMap.ConnectionName and PropertyMap.AssociationName) – if anyone finds any issues with their use please forward on to me – my test environment only included Active Directory as a source (which was the master source) so I wasn’t able to test the usage of these properties.

   1: public override int Run(string command, StringDictionary keyValues, out string output)
   2: {
   3:  output = string.Empty;
   5:  InitParameters(keyValues);
   7:  string name = Params["name"].Value;
   9:  ServerContext serverContext = ServerContext.GetContext(Params["sspname"].Value);
  10:  UserProfileConfigManager manager = new UserProfileConfigManager(serverContext);
  11:  PropertyCollection properties = manager.GetProperties();
  12:  Property property = properties.GetPropertyByName(name);
  14:  if (property == null)
  15:  {
  16:   // We couldn't find using the system name so try using the display name.
  17:   foreach (Property item in properties)
  18:   {
  19:    if (item.DisplayName.ToLowerInvariant() == name.ToLowerInvariant())
  20:    {
  21:     if (property != null)
  22:      throw new ArgumentException(string.Format("Duplicate properties found matching the name {0}.  Use the system name instead (use enumprofileprivacypolicies to get system names).", name));
  23:     property = item;
  24:    }
  25:   }
  26:  }
  28:  if (property == null)
  29:  {
  30:   throw new ArgumentException(string.Format("Could not find User Profile property '{0}'", name));
  31:  }
  34:  if (Params["description"].UserTypedIn)
  35:   property.Description = Params["description"].Value;
  37:  if (Params["displayname"].UserTypedIn)
  38:   property.DisplayName = Params["displayname"].Value;
  40:  if (Params["alias"].UserTypedIn)
  41:   property.IsAlias = bool.Parse(Params["alias"].Value);
  43:  if (Params["showchangesincolleaguetrackerwebpart"].UserTypedIn)
  44:   property.IsColleagueEventLog = bool.Parse(Params["showchangesincolleaguetrackerwebpart"].Value);
  46:  if (Params["indexed"].UserTypedIn)
  47:   property.IsSearchable = bool.Parse(Params["indexed"].Value);
  49:  if (Params["isusereditable"].UserTypedIn)
  50:   property.IsUserEditable = bool.Parse(Params["isusereditable"].Value);
  52:  if (Params["isvisibleoneditor"].UserTypedIn)
  53:   property.IsVisibleOnEditor = bool.Parse(Params["isvisibleoneditor"].Value);
  55:  if (Params["isvisibleonviewer"].UserTypedIn)
  56:   property.IsVisibleOnViewer = bool.Parse(Params["isvisibleonviewer"].Value);
  58:  if (Params["maximumshown"].UserTypedIn)
  59:   property.MaximumShown = int.Parse(Params["maximumshown"].Value);
  61:  if (Params["separator"].UserTypedIn)
  62:   property.Separator = (MultiValueSeparator)Enum.Parse(typeof(MultiValueSeparator), Params["separator"].Value, true);
  65:  if (Params["mapping"].UserTypedIn)
  66:  {
  67:   PropertyMapCollection propertyMapping = manager.GetDataSource().PropertyMapping;
  69:   if (!string.IsNullOrEmpty(Params["mapping"].Value))
  70:   {
  71:    PropertyMap map = propertyMapping[property.Name];
  73:    if (map == null)
  74:    {
  75:     string connectionName = string.Empty;
  76:     string associationName = string.Empty;
  77:     if (Params["connectionname"].UserTypedIn)
  78:      connectionName = Params["connectionname"].Value;
  79:     if (Params["associationname"].UserTypedIn)
  80:      associationName = Params["associationname"].Value;
  82:     propertyMapping.Add(property.Name, Params["mapping"].Value, connectionName, associationName);
  83:    }
  84:    else
  85:    {
  86:     map.DSPropName = Params["mapping"].Value;
  87:     if (Params["connectionname"].UserTypedIn)
  88:      map.ConnectionName = Params["connectionname"].Value;
  89:     if (Params["associationname"].UserTypedIn)
  90:      map.AssociationName = Params["associationname"].Value;
  91:     map.Commit();
  92:    }
  93:   }
  94:   else
  95:    propertyMapping.Remove(property.Name);
  96:  }
  98:  property.Commit();
 100:  return 1;
 101: }

The syntax of the command can be seen below:

C:\>stsadm -help gl-editprofileproperty

stsadm -o gl-editprofileproperty

Edits a profile property.

        -sspname <name of the SSP>
        -name <name of the profile property to edit>
        [-description <property description>]
        [-displayname <display name>]
        [-alias <true | false>]
        [-showchangesincolleaguetrackerwebpart <true | false>]
        [-indexed <true | false>]
        [-isusereditable <true | false>]
        [-isvisibleoneditor <true | false>]
        [-isvisibleonviewer <true | false>]
        [-separator <comma | semicolon>]
        [-maximumshown <maximum number of values to show before displaying ellip
sis for multi-value property>]
        [-mapping <data source field to map to (case sensitive) - leave empty to
 clear mapping>]
        [-connectionname <source data connection>]
        [-associationname <data source associated entity>]

Here’s an example of how to edit the CollegeMajor profile property identified above:

stsadm –o gl-editprofileproperty -sspname "SSP1" -name "CollegeMajor" -description "College Major" -displayname "College Major" -alias false -showchangesincolleaguetrackerwebpart false -indexed false -isusereditable true -isvisibleoneditor true -isvisibleonviewer true -mapping collegeMajor

Note that the above command assumes that "collegeMajor" exists in Active Directory (case matters).

16 thoughts on “User Profile Properties

  1. Hi! Is there a way, to generate My Site (and My Profile) to every user? As far as I know, it is generated when the user clicks on My Home… – but we want to have all users get My Profile, so we can link to it and set properties etc.

  2. Hi Gary, i’m trying to run the command

    stsadm –o gl-enumprofileproperties -sspname “SSP1” -outputfile “c:\properties.xml”

    but it just errors saying “Command line error”, any idea what could cause that?

  3. Hi gary
    Is there a way to script mapping/adding/modifying user’s profile properties with AD.

    Using GUI is too annoying and slow and i have to do this multiple time in my 7 different test environments.
    Takes a long time..

    thank you

  4. Any thoughts on writing something for 2010? I’m dreading having to click 1 million times to get all of the properties added and in the right order.

  5. I have plans to migrate my user profile commands to 2010 but just haven’t had time. I may work on them in the next couple of weeks though as I have some stuff I need for a demo that I’m putting together.

  6. Hello,
    after migrating you blog to this address i only see the comments, not the blog post itself. Browser is IE 8.

  7. Hi Gary,
    Have you made a 2010 version of this tool? I am trying to do a migration from 2007 to 2010, and I am not bringing over the user profiles with an upgrade. I just need to make sure I have the mappings exact when I set it up on the new server.

  8. HI Gary,

    i need to export the user profile properties (settings) from one SHarepoint 2010 environment to another Sharepoint 2010 environment. PLease advise.

    1. You can use PowerShell to iterate through all the properties and save the details to an XML file and then use another script to read that XML file and do the import.

Comments are closed.