I've moved my blog to!. Please update your links. This blog is no longer in use--you can find all posts and comments at my new blog; I will no longer be posting to this site and comments have been disabled.

Sunday, May 18, 2008

Profile Import Timer Job

I was recently trying to debug some issues that I was having with the people picker that is shown when creating audiences and I found that I needed a way to manually trigger the distribution list import quickly but I didn't always want to have to wait for the user profile import to finish.  If you run an import using the SSP admin site you might notice that it imports all the user profile information and then it imports the distribution list information but there's no way (at least that I could find) to do just the distribution list.  So I created a new command which I called gl-runprofileimportjob which allows me to run the profile import.

Fortunately it turned out that the code to do this is really simple - you just need an instance of the UserProfileConfigManager and you call either StartImport() or StartDLImport().  To keep the command from exiting before the import is complete I check the IsImportInProgress method and loop until it is set to false:

   1: public class RunProfileImportJob : SPOperation
   2: {
   3:     /// <summary>
   4:     /// Initializes a new instance of the <see cref="RunProfileImportJob"/> class.
   5:     /// </summary>
   6:     public RunProfileImportJob()
   7:     {
   8:         SPParamCollection parameters = new SPParamCollection();
   9:         parameters.Add(new SPParam("sspname", "ssp", false, null, new SPNonEmptyValidator()));
  10:         parameters.Add(new SPParam("distributionlistonly", "dl"));
  11:         parameters.Add(new SPParam("incremental", "inc"));
  13:         StringBuilder sb = new StringBuilder();
  14:         sb.Append("\r\n\r\nExecutes a Profile Import.\r\n\r\nParameters:");
  15:         sb.Append("\r\n\t-sspname <SSP Name>");
  16:         sb.Append("\r\n\t[-distributionlistonly]");
  17:         sb.Append("\r\n\t[-incremental]");
  19:         Init(parameters, sb.ToString());
  20:     }
  22:     /// <summary>
  23:     /// Gets the help message.
  24:     /// </summary>
  25:     /// <param name="command">The command.</param>
  26:     /// <returns></returns>
  27:     public override string GetHelpMessage(string command)
  28:     {
  29:         return HelpMessage;
  30:     }
  32:     /// <summary>
  33:     /// Executes the specified command.
  34:     /// </summary>
  35:     /// <param name="command">The command.</param>
  36:     /// <param name="keyValues">The key values.</param>
  37:     /// <param name="output">The output.</param>
  38:     /// <returns></returns>
  39:     public override int Execute(string command, System.Collections.Specialized.StringDictionary keyValues, out string output)
  40:     {
  41:         output = string.Empty;
  43:         string sspName = Params["sspname"].Value;
  44:         bool dlOnly = Params["distributionlistonly"].UserTypedIn;
  45:         bool incremental = Params["incremental"].UserTypedIn;
  47:         UserProfileConfigManager manager = new UserProfileConfigManager(ServerContext.GetContext(sspName));
  48:         if (!manager.IsImportInProgress())
  49:         {
  50:             if (dlOnly)
  51:                 manager.StartDLImport();
  52:             else
  53:                 manager.StartImport(incremental);
  55:             Console.Write("Executing import...");
  56:             while (manager.IsImportInProgress())
  57:             {
  58:                 Thread.Sleep(500);
  59:                 Console.Write(".");
  60:             }
  61:             Console.WriteLine();
  62:             Console.WriteLine();
  63:         }
  64:         else
  65:         {
  66:             Console.WriteLine("Import is already running.");
  67:         }
  69:         return OUTPUT_SUCCESS;
  70:     }
  72: }

The syntax of the command can be seen below:

C:\>stsadm -help gl-runprofileimportjob

stsadm -o gl-runprofileimportjob

Executes a Profile Import.

        -sspname <SSP Name>

Here's an example of how to run the command to import just the distribution lists:

stsadm -o gl-runprofileimportjob -sspname SSP1 -distributionlistonly

Note that the "-incremental" flag is only relevant when the "-distributionlistonly" flag is not provided.


Adam Toth said...

Perfect. I've hated having to wait for a full profile import, and then wait up to another five minutes for the timer job to kick off the distribution list import.


bekz said...

Hi Gary,

This is really helpful!

I have a query with regard to this. Can I find how the profile import timer works? From it seems that those timers are hidden. I would like to see how they are doing the import.

Any thoughts?


Gary Lapointe said...

Unfortunately most of the key code that is doing the actual import is all obfuscated so it would be very difficult to work through it (using Reflector or something similar) to see exactly how it works.

bekz said...

Thanks Gary,

Yeah! StartImport() is obfuscated as you told.

Now another query that I have is SSP discovers the user info from the WSS web apps. Is that done using the "Profile Synchronization" timers. i.e. Are those doing a two way sync between SSP and WSS web application?


Manas/Tapan said...

I have changed my domain username and password which was used to install sharepoint server 2007
Now the moment the the sharepoint timer service is 'started' I am getting login error and eventually my domain/user is getting locked. I guess the change in the active directory is not reflected. Is there any way I can set the user, password for the timer job ?

Gary Lapointe said...

You need to also change the password via SharePoint (let SP know about the new password). See my downloads page for a link to a password change script.